2012-02-15 19 views
7

Mam wskaźniki Base * do dwóch wystąpień typu polimorficznego i muszę ustalić, czy obiekty, do których istnieją odwołania, są równoważne.Czy istnieje podejście idiomatyczne w C++ do porównywania typów polimorficznych dla równoważności obiektów?

Moje obecne podejście polega na tym, aby najpierw użyć RTTI do sprawdzenia równości typu. Jeśli typy są równe, wówczas wywołuję funkcję virtual is_equivalent.

Czy istnieje podejście bardziej idiomatyczne?

+1

Jakie są równoważne obiekty według ciebie? –

+0

Dla większości klas pochodnych, odpowiednik oznacza po prostu, że zmienne składowe mają tę samą wartość. – RandomBits

+0

To pytanie może być powiązane: http://stackoverflow.com/questions/1691007/whats-the-right-way-to-overload-operator-for-a-class-hierarchy –

Odpowiedz

6

Dla większości klas pochodnych, co odpowiada po prostu oznacza, że ​​zmienne składowe wszystkich samą wartość

W C++ jest to nazywane „równość” i jest zazwyczaj realizowane za pomocą operator==(). W C++ można zastąpić znaczenie operatorów, możliwe jest, aby napisać:

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

I mieć == połączenia niestandardowych funkcji można zdefiniować.

Myślę, że chcesz odróżnić równość od tożsamości, która oznaczałaby ten sam obiekt (to znaczy ten sam adres).

można wdrożyć go jako funkcji składowej lub wolnego funkcji (z Wikipedii):

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

W twoim przypadku chcesz realizować operator== dla klasy bazowej, a następnie wykonaj co robisz.

Bardziej konkretnie to będzie wyglądać następująco:

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

W funkcji 'operator ==' chciałbym wywołać funkcję wirtualną, aby porównać dwa obiekty. Czy podpis funkcji porównania powinien być czymś w rodzaju 'virtual bool is_equal (MyBase const &)'. Wydaje się to działać, ale wymaga wyraźnego downcast w implementacji 'is_equal', aby uzyskać typ obiektu pochodnego. – RandomBits

+0

Tak, powinien to być podpis. (Przepraszam, edytuj) Tak, wymaga obsady. Możesz określić, że 'is_equal' musi być wywołany z obiektem w tym samym typie, uczyń go prywatnym, aby tylko mógł go wywoływać' == '(w takim przypadku musisz zadeklarować swojego operatora jako znajomego). –

+0

Zapomniałeś części "przyjaciel" w swojej edycji i "wirtualnej". Dodałem go (ale nie przetestowałem). –

Powiązane problemy