2012-02-15 8 views
7

Ho i puntatori Base * su due istanze di un tipo polimorfico e devo determinare se gli oggetti di riferimento sono equivalenti.Esiste un approccio idiomatico in C++ per confrontare i tipi polimorfici per l'equivalenza degli oggetti?

Il mio attuale approccio è di utilizzare prima RTTI per verificare l'uguaglianza di tipo. Se i tipi sono uguali, allora chiamo una funzione is_equivalent virtuale.

C'è un approccio più idiomatico?

+1

Quali sono oggetti equivalenti secondo te? –

+0

Per la maggior parte delle classi derivate, equivalente significa semplicemente che le variabili membro hanno tutti lo stesso valore. – RandomBits

+0

Questa domanda potrebbe essere correlata: http://stackoverflow.com/questions/1691007/whats-the-right-way-to-overload-operator-for-a-class-hierarchy –

risposta

6

Per la maggior parte delle classi derivate, equivalente significa semplicemente che le variabili membro lo stesso valore

In C++ questo è chiamato 'uguaglianza' e di solito è implementato utilizzando operator==(). In C++ è possibile ignorare il significato degli operatori, è possibile scrivere:

MyType A; 
MyType B; 
if (A == B) { 
    // do stuff 
} 

E hanno == chiamata di una funzione personalizzata si definisce.

Penso che vogliate differenziare l'uguaglianza dall'identità che significherebbe lo stesso oggetto (cioè lo stesso indirizzo).

è possibile implementare come funzione membro o la funzione libera (da wikipedia):

bool T::operator ==(const T& b) const; 
bool operator ==(const T& a, const T& b); 

Nel tuo caso si desidera implementare operator== per la classe base, e quindi eseguire quello che stai facendo.

Più concretamente si sarebbe simile a questa:

class MyBase 
{ 
    virtual ~MyBase(); // reminder on virtual destructor for RTTI 
    // ... 
private: 
    virtual bool is_equal(const MyBase& other); 

    friend bool operator ==(const MyBase& a, const MyBase& b); 

    // ...  
}; 

bool operator ==(const MyBase& a, const MyBase& b) 
{ 
    // RTTI check 
    if (typeid(a) != typeid(b)) 
     return false; 
    // Invoke is_equal on derived types 
    return a.is_equal(b); 
} 


class D1 : MyBase 
{ 
    virtual bool is_equal(const Base& other) 
    { 
     const D1& other_derived = dynamic_cast<const D1&>(other); 
     // Now compare *this to other_derived 
    } 
}; 

class D2 : MyBase; 
{ }; 


D1 d1; D2 d2; 
bool equal = d1 == d2; // will call your operator and return false since 
         // RTTI will say the types are different 
+0

Nella funzione 'operator ==', vorrei chiamare una funzione virtuale per confrontare i due oggetti. La firma della funzione di confronto dovrebbe essere qualcosa come 'virtual bool is_equal (MyBase const &)'. Questo sembra funzionare ma richiede un downcast esplicito nell'implementazione di 'is_equal' per ottenere il tipo di oggetto derivato. – RandomBits

+0

Sì, dovrebbe essere la firma. (Scusa, modifica) Sì, richiede un cast. È possibile specificare che 'is_equal' deve essere chiamato con un oggetto nello stesso tipo, renderlo privato in modo che solo' == 'possa chiamarlo (in tal caso è necessario dichiarare il proprio operatore come amico). –

+0

Hai dimenticato la parte "amico" nella tua modifica e un 'virtuale'. L'ho aggiunto (ma non testato). –