2009-02-19 9 views
9

Ho una classe base che implementa l'operatore ==. Voglio scrivere un'altra classe, ereditando la classe base e quale dovrebbe reimplementare l'operatore ==.implementazione dell'operatore == quando si utilizza l'ereditarietà

Ecco alcuni esempi di codice:

#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"; 
    } 
} 

Questo codice di esempio il seguente risultato:

different employee 
same person 

Dove vorrei, anche nel caso di persona * puntatori, per assicurarsi che essi sono diversi .

Come posso risolvere questo problema?

Grazie!

+0

credo che tu stia cercando di risolvere il problema sbagliato. se hai bisogno di un operatore == che funzioni in base al tipo di riferimento/puntatore non dovresti aver usato l'ereditarietà in primo luogo. – hawk

risposta

8

Quello che si vuole fare è "virtualizzare" l'operatore di confronto.

Poiché gli operatori non possono essere virtuali, è necessario delegarlo a qualcos'altro. Ecco una possibile soluzione.

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 domanda non chiariva se la Persona ha bisogno di essere una classe concreta. In tal caso, puoi renderlo non puramente virtuale e implementarlo per restituire true.

Questo utilizza anche RTTI, di cui potresti non essere soddisfatto.

+0

C++ permette agli operatori di essere virtuali. ma non li renderei virtuali. il polimorfismo e gli operatori in realtà non si adattano molto bene (e le funzioni libere dell'operatore ovviamente non possono essere virtuali). –

+4

Se avete intenzione di fare questo, allora dovreste chiamare sia 'this-> doCompare (that)' che 'that.doCompare (* this)' per assicurare la simmetria –

0

È necessario rendere Person :: operator == virtual.

+0

-1. Rendere Person :: operator == virtual non è sufficiente: Employee :: operator == deve essere riscritto per avere la stessa firma. Inoltre, ciò porterebbe ancora al problema indicato da Douglas, cioè l'assimetria dell'operazione di confronto, che è ... strana. –

+0

Non penso che tu possa rendere gli operatori virtuali. – JohnMcG

7

aggiungere una funzione int virtual Confronta (const Person & rPerson) e l'uso che nei vostri operatori

5

Non esiste una soluzione ordinata a questo problema.

Quale non è un problema in realtà, in C++. Che senso ha fare per confrontare le entità su una base di uguaglianza?

EDIT: alcuni link a meditare per quanto riguarda la pertinenza di uguaglianza applicata a soggetti:

+0

Non capisco il tuo punto. Puoi spiegare in modo più dettagliato, perché un simile confronto non ha senso? – jpfollenius

+0

Il mio punto è che l'uguaglianza non ha senso sulle entità, e che l'OP sta sprecando i suoi tempi per risolvere qualcosa che non deve essere risolto, né può essere risolto (vedi Java dibattiti sull'implementazione di isEquals) –

+0

... Prendi due gemelli, sono molto simile, in un certo senso potremmo vederli come uguali. Ma a chi importa ? Le persone sono identiche o no ... –

5

Hai ancora un grosso problema se hai una persona e un dipendente - la persona può essere paragonata al dipendente, ma non il dipendente alla persona. Ad esempio:

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

Questa è una cosa negativa (tm). In pratica hai fatto un operatore di uguaglianza che non è symmetric

Edit:

Ok, nessun operatori virtuali - aggiungono il virtuale Funzione di confronto suggerito altrove, credo - ma avete ancora il problema simmetrico.

0

È anche possibile utilizzare l'operatore == al di fuori dell'ambito della classe. In tal caso, è possibile creare sovraccarichi necessari o renderli generici mediante modelli.

2

La grande domanda qui è: come si determina l'uguaglianza?

È possibile confrontare qualsiasi oggetto con qualsiasi altro oggetto nella gerarchia? Si possono confrontare solo oggetti dello stesso tipo? Dove vivono i criteri per il confronto?

L'implementazione della soluzione dipenderà dalle risposte a queste domande.

1

Non ha senso avere la stessa persona uguale a due dipendenti diversi, ma questo è ciò che consente il disegno di classe.Stai meglio organizzando l'identità per essere attaccato a una persona. Quindi chiedi se a.identity() == b.identity().

1

Al fine di rendere operator== simmetrica bisogna avere una persona e dei dipendenti con gli stessi dettagli condivisi differiscono in modo che:

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

Questo è poco intuitivo, ma necessario.

Per fare questo è possibile utilizzare il typeid keyword

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

Naturalmente Person deve essere un tipo polimorfico (hanno almeno una funzione virtuale).

Problemi correlati