2009-02-19 17 views
9

Tengo una clase base que implementa el operador ==. Quiero escribir otra clase, heredar la clase base y que debe volver a implementar el operador ==.implementando el operador == cuando se usa la herencia

Aquí hay un código de ejemplo:

#include <iostream> 
#include <string> 

class Person 
{ 
public: 
    Person(std::string Name) { m_Name = Name; }; 

    bool operator==(const Person& rPerson) 
    { 
    return m_Name == rPerson.m_Name; 
    } 

private: 
    std::string m_Name; 
}; 

class Employee : public Person 
{ 
public: 
    Employee(std::string Name, int Id) : Person(Name) { m_Id = Id; }; 

    bool operator==(const Employee& rEmployee) 
    { 

    return (Person::operator==(rEmployee)) && (m_Id == rEmployee.m_Id); 
    } 

private: 
    int m_Id; 
}; 

void main() 
{ 
    Employee* pEmployee1 = new Employee("Foo" , 1); 
    Employee* pEmployee2 = new Employee("Foo" , 2); 

    if (*pEmployee1 == *pEmployee2) 
    { 
    std::cout << "same employee\n"; 
    } 
    else 
    { 
    std::cout << "different employee\n"; 
    } 

    Person* pPerson1 = pEmployee1; 
    Person* pPerson2 = pEmployee2; 

    if (*pPerson1 == *pPerson2) 
    { 
    std::cout << "same person\n"; 
    } 
    else 
    { 
    std::cout << "different person\n"; 
    } 
} 

Este código de ejemplo da el siguiente resultado:

different employee 
same person 

Donde quisiera, incluso al manejar persona * punteros, para asegurarse de que son diferentes .

¿Cómo se supone que voy a resolver este problema?

Gracias!

+0

Creo que está tratando de resolver el problema equivocado. si necesita un operador == que funcione según el tipo de referencia/puntero, no debería haber usado la herencia en primer lugar. – hawk

Respuesta

8

Lo que quiere hacer es esencial "virtualizar" el operador de comparación.

Dado que los operadores no pueden ser virtuales, tendrá que delegarlo a otra cosa. Aquí hay una posible solución.

class Person 
{ 
    public: 
     /* ... */ 
     bool operator==(const Person& rhs) 
     { 
     return m_Name == rPerson.m_Name && this->doCompare(rhs); 
     } 
    private: 
     virtual bool doCompare() = 0; 
    }; 
} 
class Employee : public Person 
{ 
    /* ... */ 
    private: 
     virtual bool doCompare(const Person& rhs) 
     { 
     bool bRetval = false; 
     const Employee* pRHSEmployee = dynamic_cast<const Employee*>(&rhs); 
     if (pEmployee) 
     { 
      bRetval = m_Id == pRHSEmployee->m_Id 
     } 
     return bRetval; 
     } 
}; 

La pregunta no dejaba claro si la persona tiene que ser una clase concreta. Si es así, puede hacer que no sea puramente virtual e implementarlo para que sea verdadero.

Esto también usa RTTI, con lo que puede o no ser feliz.

+0

C++ permite a los operadores ser virtuales. pero no los haría virtuales. el polimorfismo y los operadores en realidad no encajan muy bien (y las funciones gratuitas del operador obviamente no pueden ser virtuales en absoluto). –

+4

Si va a hacer esto, debe llamar a 'this-> doCompare (that)' y 'that.doCompare (* this)' para garantizar la simetría –

0

Tiene que hacer que Person :: operator == virtual.

+0

-1. Hacer que Person :: operator == virtual no sea suficiente: Employee :: operator == debe reescribirse para tener la misma firma. Además, esto todavía llevaría al problema señalado por Douglas, es decir, la asimetría de la operación de comparación, que es ... rara. –

+0

No creo que puedas hacer que los operadores sean virtuales. – JohnMcG

7

Añadir un int función virtual Comparar (const persona & rPerson) y el uso que en sus operadores

5

No hay una solución ordenada a este problema.

Lo que no es un problema en realidad, en C++. ¿Qué sentido tiene comparar entidades en términos de igualdad?

EDIT: algunos enlaces para meditar en cuanto a la pertinencia de la igualdad se aplica a las entidades:

+0

No entiendo tu punto. ¿Puedes explicar con más detalle por qué tal comparación no tiene sentido? – jpfollenius

+0

Mi punto es que la igualdad no tiene sentido en las entidades, y que el OP está perdiendo el tiempo resolviendo algo que no debe ser resuelto, ni puede ser resuelto (ver los debates de Java sobre la implementación de isEquals) –

+0

... Tomar gemelos, son muy similar, en cierto sentido, podemos verlos como iguales. Pero a quién le importa ? Las personas son idénticas, o no ... –

5

Todavía tiene un problema importante si tiene una persona y un empleado: la persona puede comparar igual que el empleado, pero no el empleado con la persona. es decir:

(employee == person) != (person == employee) 

Esto es una mala cosa (tm). Básicamente usted ha hecho un operador de igualdad que no es symmetric

Editar:

, no hay operadores virtuales Ok - añada lo virtual función de comparación sugerido en otra parte creo - pero todavía tiene el problema simétrico.

0

También puede tomar operador == fuera del alcance de la clase. En ese caso, puede crear sobrecargas necesarias o hacerlo genérico mediante plantillas.

2

La gran pregunta aquí es: ¿cómo se determina la igualdad?

¿Se puede comparar cualquier objeto con cualquier otro objeto en la jerarquía? ¿Solo se pueden comparar objetos del mismo tipo? ¿Dónde viven los criterios para la comparación?

La implementación de la solución dependerá de las respuestas a estas preguntas.

1

No tiene sentido que la misma persona sea igual a dos empleados diferentes, pero eso es lo que permite el diseño de clase.Es mejor que organices la identidad de una persona. Luego pregunta si a.identity() == b.identity().

1

Con el fin de hacer operator== simétrica que tiene que tener una persona y de los empleados con los mismos datos compartidos difieren de manera que:

Person p("Foo"); 
Employee e("Foo" , 1); 
p == e; // false 
e == p; // false 

Esto es poco intuitivo, pero es necesario.

Para ello puede utilizar el typeid keyword

bool operator==(const Person& other) const 
{ 
    return m_Name == other.m_Name && typeid(other) == typeid(*this); 
} 

Por supuesto Person debe ser un tipo polimórfico (tener al menos una función virtual).

Cuestiones relacionadas