Actualmente estoy creando una clase de utilidad que tendrá operadores sobrecargados. ¿Cuáles son los pros y los contras de hacerlos miembros o no miembros (friend
) funciones? ¿O importa para nada? Tal vez hay una mejor práctica para esto?¿Operadores de sobrecarga como función miembro o función no miembro (amigo)?
Respuesta
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).
No hay nada como las mejores prácticas pero depende del operador que se está sobrecargando ..
Para por ejemplo.
>> y < < no puede sobrecargarse como funciones miembro.
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.
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;
}
¿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 ... –
@Matthieu M., nos impide escribir "(a + b) = c", que ya es nativamente imposible con tipos primitivos como int. –
@Jagannath, Olvidaste el "const" para ambas declaraciones de parámetros. –
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.
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.
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.
- 1. sobrecarga del operador (función de amigo y miembro)
- 2. Operador sobrecarga = como No miembro
- 3. Sobrecarga del operador: función de miembro vs. función de no miembro?
- 4. Importancia del operador de sobrecarga -() como función libre y no función de miembro?
- 5. ¿Por qué la función de miembro amigo no se reconoce como plantilla de función automáticamente?
- 6. unary minus overload: miembro o no miembro?
- 7. Hacer que un miembro funcione como amigo
- 8. Puntero como miembro o Referencia como miembro
- 9. Puntero de función C++ como miembro estático
- 10. decltype (función) como miembro de la clase
- 11. miembro definición de función
- 12. plantillas miembro de función y operador de sobrecarga() en C++
- 13. ¿Ventajas de utilizar una función miembro estática en lugar de una función miembro no estático equivalente?
- 14. Puntero de función a función de miembro
- 15. Miembro no estático como argumento predeterminado de una función miembro no estática
- 16. ¿Cuándo debería preferir las funciones de no amigo no miembro a las funciones de miembro?
- 17. Pasar la función puntero a miembro como puntero a función
- 18. Puntero de función de miembro
- 19. ¿Especifica una función de miembro de clase como amigo de otra clase?
- 20. Llamar a una función de miembro no const desde una función de miembro constante
- 21. función miembro que oculta la función libre
- 22. QtConcurrent con función de miembro
- 23. ¿Cuál es la semántica de una función miembro miembro?
- 24. C++ función de amigo - sobrecarga del operador istream >>
- 25. ¿Referencia a la función miembro?
- 26. clasificación de problemas usando la función de miembro como comparador
- 27. puntero de función miembro que devuelve mismo tipo de puntero de función miembro
- 28. genérica puntero de función miembro como un parámetro de plantilla
- 29. puntero de función de miembro de fundición
- 30. Indicadores de función de miembro y herencia
cout y cin son instancias de clases en iostream, no se pueden sobrecargar, OP está hablando de operadores de sobrecarga. –
gracias lo he corregido. – Ashish
'<<' 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. –