sobrecargar sobrecargados sobrecarga sirve que para operadores operador matrices herencia constructores c++ operators operator-overloading

sobrecargados - sobrecarga del operador<< c++



¿Por qué definir operador+o+= fuera de una clase y cómo hacerlo correctamente? (3)

El especificador de friend se utiliza cuando lo que se declara no es un miembro de la clase, pero necesita acceso a los miembros privados de las instancias de la clase para poder realizar su trabajo.

Si su operador se definirá en la clase en sí, use la primera forma; si va a ser una función independiente, use la segunda.

Estoy un poco confundido acerca de las diferencias entre

Type operator + (const Type &type); Type &operator += (const Type &type);

y

friend Type operator + (const Type &type1, const Type &type2); friend Type &operator += (const Type &type1, const Type &type2);

¿De qué manera se prefiere, cómo se ven y cuándo deben usarse?


La forma correcta de implementar operadores, con respecto a C ++ 03 y C ++ 0x ( NRVO y semántica de movimiento), es:

struct foo { // mutates left-operand => member-function foo& operator+=(const foo& other) { x += other.x; return *this; } int x; }; // non-mutating => non-member function foo operator+(foo first, // parameter as value, move-construct (or elide) const foo& second) { first += second; // implement in terms of mutating operator return first; // NRVO (or move-construct) }

Tenga en cuenta que es tentador combinar lo anterior en:

foo operator+(foo first, const foo& second) { return first += second; }

Pero a veces (en mis pruebas) el compilador no habilita NRVO (o mueve la semántica) porque no puede estar seguro (hasta que inscribe al operador mutante) que first += second es lo mismo que first . Más simple y seguro es dividirlo.


La primera forma de los operadores es lo que definirías dentro de la clase Type .

La segunda forma de los operadores es lo que definiría como funciones independientes en el mismo espacio de nombres que el Type clase.

Es una muy buena idea definir funciones independientes porque entonces los operandos de aquellos pueden participar en las conversiones implícitas .

Ejemplo

Supongamos esta clase:

class Type { public: Type(int foo) { } // Added the const qualifier as an update: see end of answer Type operator + (const Type& type) const { return *this; } };

Entonces podrías escribir:

Type a = Type(1) + Type(2); // OK Type b = Type(1) + 2; // Also OK: conversion of int(2) to Type

Pero NO puedes escribir:

Type c = 1 + Type(2); // DOES NOT COMPILE

Tener el operator+ como una función gratuita también permite el último caso.

Sin embargo, lo que la segunda forma del operador hace mal es que realiza la adición mediante el ajuste directo de los miembros privados de sus operandos (asumo que, de lo contrario, no tendría que ser un amigo). No debería estar haciendo eso: en su lugar, los operadores también deberían definirse dentro de la clase y las funciones independientes deberían llamarlos.

Para ver cómo resultaría eso, pidamos los servicios de un gurú: http://www.gotw.ca/gotw/004.htm . Desplácese hasta el final para ver cómo implementar las funciones independientes.

Actualizar:

Como dice James McNellis en su comentario, las dos formas dadas también tienen otra diferencia: el lado izquierdo no está calificado en la primera versión. Dado que los operandos de operator+ realmente no deben modificarse como parte de la adición, es una muy buena idea regularlos constantemente. El Type clase en mi ejemplo ahora hace esto, donde inicialmente no lo hizo.

Conclusión

La mejor manera de tratar con los operadores + y += es:

  1. Definir operator+= como T& T::operator+=(const T&); dentro de tu clase Aquí es donde se implementaría la adición.
  2. Defina operator+ como TT::operator+(const T&) const; dentro de tu clase Este operador sería implementado en términos del anterior.
  3. Proporcionar una función libre T operator+(const T&, const T&); fuera de la clase, pero dentro del mismo espacio de nombres. Esta función llamaría al operator+ miembro operator+ para hacer el trabajo.

Puede omitir el paso 2 y hacer que la función gratuita llame a T::operator+= directamente, pero como cuestión de preferencia personal, quisiera mantener toda la lógica de adición dentro de la clase.