2009-12-15 17 views

Respuesta

16

Cada operador tiene sus propias consideraciones. Por ejemplo, el operador < < (cuando se usa para transmisión de flujo, no para cambio de bit) obtiene un ostream como primer parámetro, por lo que no puede ser miembro de su clase. Si está implementando el operador adicional, probablemente querrá beneficiarse de las conversiones de tipo automáticas en ambos lados, por lo tanto irá con un no miembro también, etc ...

En cuanto a permitir la especialización a través herencia, un patrón común es implementar un operador no miembro en términos de una función de miembro virtual (por ejemplo, el operador < < llama a una función virtual print() en el objeto que se pasa).

0

No hay nada como las mejores prácticas pero depende del operador que se está sobrecargando ..

Para por ejemplo.

  1. >> y < < no puede sobrecargarse como funciones miembro.

  2. Supongamos que quiere hacer de esta manera: obj1 = 2 * obj2 y luego ir por la función no miembros.

Para operador binario sobrecarga función miembro tarda sólo 1 parámetro (objeto invocando se pasa impcliitly) mientras que la función no miembro toma 2 parámetros.

+3

cout y cin son instancias de clases en iostream, no se pueden sobrecargar, OP está hablando de operadores de sobrecarga. –

+0

gracias lo he corregido. – Ashish

+2

'<<' and '>>' ciertamente pueden estar sobrecargados como funciones miembro, solo que no si desea usarlos como operadores de extracción/inserción de flujo. Si desea usarlos como operadores de turno, como lo pretendía Dennis Ritchie, no hay problema. –

3

Si está implementando op, entonces lo más probable es que necesite implementar op =. es decir, si está sobrecargando el operador +, entonces debe implementar + =. Asegúrese de estar devolviendo const a un objeto si está realizando un incremento o una sobrecarga + operador. Por lo tanto, si sobrecarga el operador +, impleméntelo como un operador no miembro y use el operador + = dentro de él. Por ej.

const A operator+(const A& lhs, const A& rhs) 
{ 
    A ret(lhs); 
    ret += rhs; 
    return ret; 
} 
+0

¿Cuál es el punto de devolver 'const A'? Lo he visto algunas veces (devolviendo un valor constante) y nunca pude encontrar ninguna razón práctica ... –

+0

@Matthieu M., nos impide escribir "(a + b) = c", que ya es nativamente imposible con tipos primitivos como int. –

+1

@Jagannath, Olvidaste el "const" para ambas declaraciones de parámetros. –

2

Para los operadores binarios, una de las funciones de los miembros es que el objeto izquierdo debe ser de su clase. Esto puede limitar el uso simétrico del operador.

Considérese una clase simple cadena:

class str 
{ 
public: 
    str(const char *); 
    str(const str &other); 
}; 

Si implementa operador + como una función miembro, mientras que str("1") + "2" compilará, se "1" + str("2") no compilar.

Pero si implementa operador + como una función no miembro, entonces ambas declaraciones serán legales.

3

Si planea implementar operadores de transmisión (< < y >>), entonces serán métodos que no son miembros porque su objeto está a la izquierda del operador.

Si planea implementar ->,() o [], son métodos que naturalmente son miembros.

Para los demás (comparación y matemática) que debe consultar Boost.Operators, realmente ayuda.

Por ejemplo, si se desea implementar los siguientes operadores:

MyClass& MyClass::operator+=(int); 
MyClass operator+(const MyClass&, int); 
MyClass operator+(int, const MyClass&); 

Sólo tiene que escribir:

class MyClass: boost::operator::addable<MyClass,int> // no need for public there 
{ 
public: 
    MyClass& operator+=(int); 
private: 
}; 

El 2 operator+ se generará automáticamente como no miembros que le permitirá se beneficia de las conversiones automáticas. Y se implementarán de manera eficiente en el término operator+=, por lo que debe escribir el código solo una vez.

20

Me gustaría ir con "Estándares de codificación C++: 101 Reglas, pautas y mejores prácticas": si puede hacerlo como función no miembro, hágalo como función no miembro (en el mismo espacio de nombres).

Una de las razones: funciona mejor con la conversión de tipo implícita. Un ejemplo: tiene una clase compleja con un operador sobrecargado *. Si desea escribir 2.0 * aComplexNumber, necesita que el operador * sea una función no miembro.

Otra razón: menos acoplamiento. Las funciones no miembro se combinan menos estrechamente que las funciones miembro. Esto es casi siempre algo bueno.

Cuestiones relacionadas