2012-05-13 29 views
29

¿Cuál es la mejor práctica (en este caso):Operador de comparación sobrecarga

bool Foo::operator==(const Foo& other) { 
    return bar == other.bar; 
} 

// Implementation 1 
bool Foo::operator!=(const Foo& other) { 
    return bar != other.bar 
} 

// Implementation 2 
bool Foo::operator!=(const Foo& other) { 
    return !(*this == other); 
} 

Para los operadores como>, <, < =,> = Me gustaría ir con aplicación 2 cuando sea posible. Sin embargo, para! = Creo que la implementación 1 es mejor ya que no se realiza otra llamada al método, ¿es correcto?

+0

Lo escribiría de la manera más natural para expresarlo correctamente. Es probable que el compilador haga un buen trabajo de compilación en cualquier momento que elija. – Flexo

+0

Ok gracias. Como nota al margen, sé que si el == es demasiado complejo, entonces la implementación 2 sería mejor, pero ese es otro caso. – blaze

+0

Debe agregar un 'const' a cada una de las funciones. Considere también el uso de funciones gratuitas en lugar de funciones de miembros, ya que las primeras son simétricas con respecto a los tipos y las conversiones donde estos últimos no lo son. Esto es más importante si su tipo se puede convertir implícitamente de otros tipos. –

Respuesta

29

La segunda implementación tiene la limitación notable de que == siempre será el booleano opuesto al !=. Esto es probablemente lo que desea, y hace que su código sea más fácil de mantener porque solo tiene que cambiar una implementación para mantener los dos sincronizados.

+7

Y cada compilador de C++ en el planeta alineará la llamada de! = ==. – jthill

+1

@jthill Tenga cuidado: no lo hará si el operador aún no está definido (por ejemplo, archivos de origen). – Tim

+3

@Tim, podría hacerlo si su compilador tiene LTO. – zneak

11

Siempre debe usar lo que tiene al sobrecargar operadores de comparación. Los únicos dos que debe definir son operator== y operator<. El resto lo puedes escribir en términos de estos dos. Es menos propenso a errores, como si tuviera un error, es solo en un lugar.

Una de las principales características de OOP es la reutilización del código. Si ya ha escrito el código, ¿por qué volver a escribirlo? Quédese con lo que tiene, y solo tendrá una cosa para probar.

Es más bien como declarar una constante y luego usarla en varios puntos de su archivo.

+0

En realidad, solo necesita '' operator <''. Porque x == y es lógicamente equivalente a! (X mdenton8

+0

@ mdenton8, claro, pero es idiomático definir tanto 'operator '' como 'operator ==' desde cero si quiere todos los operadores de comparación. Algunos algoritmos y contenedores STL de C++ usarán 'operator ==' para la igualdad y algunos usarán 'operator '' en la forma que usted describió. Es cierto que si hacen cosas diferentes, es posible que tengas resultados sorprendentes al usar ciertos algoritmos. – chris

+0

Es cierto que a menudo puede ser más eficiente y más claro. Pero menos sostenible por las mismas razones que mencionaste anteriormente. – mdenton8

4

La implementación 2 es mejor porque hace uso del operador ya definido ==. También esas funciones del operador deben ser const porque no modifican el objeto.

+0

Gracias por la punta const – blaze

+0

No puedo estar seguro de lo que exactamente sobre mi configuración causó esto (boost.optional, tal vez), pero tengo un bote de errores como 'stl_algobase.h: 808: 22: error: no se puede encontrar ' operador == ''hasta que declare las funciones' const' Gracias por señalar esto. – MatrixManAtYrService

1

En general, la implementación 2 es mejor por muchas razones. En primer lugar, no escribe (casi) código duplicado. Si necesita cambiarlo (porque la clase ha crecido o ha habido un error), nuevamente con la implementación 2, cambia solo 1 lugar. Es decir, la implementación 2 hace que su código sea más consistente y menos propenso a errores.

3

Ninguno de los de arriba.

Ojalá pudiera encontrar el documento que realmente trata este tema en detalle, pero no recuerdo el nombre.

Sus operaciones de comparación deben ser externas. Su interfaz debe ser suficiente para encontrar el estado de un objeto y el estado del objeto debe dictar la comparación. Debería ser posible escribir "iguales" fuera de su clase, y por lo tanto cualquier comparación en realidad, y que eso sea posible ... lo desea.

+2

Esto no siempre es cierto. Puede haber diseños en los que no desee otorgar acceso a todo el estado. Por otra parte, siempre puede otorgar acceso a una función gratuita a través de la amistad. –