Есть ли идиоматический подход в C ++ для сравнения полиморфных типов на предмет эквивалентности? - PullRequest
7 голосов
/ 15 февраля 2012

У меня есть Base * указатели на два экземпляра полиморфного типа, и мне нужно определить, эквивалентны ли ссылочные объекты.

Мой текущий подход заключается в том, чтобы сначала использовать RTTI для проверки на равенство типов. Если типы равны, я вызываю виртуальную функцию is_equivalent.

Есть ли более идиоматический подход?

1 Ответ

6 голосов
/ 15 февраля 2012

Для большинства производных классов эквивалент просто означает, что переменные-члены имеют одно и то же значение

В C ++ это называется «равенством» и обычно реализуется с использованием operator==().В C ++ вы можете переопределить значение операторов, можно написать:

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

И заставить == вызывать пользовательскую функцию, которую вы определяете.

Я думаю, что вы хотите различать равенствоот идентичности, которая будет означать один и тот же объект (т.е. тот же адрес).

Вы можете реализовать его как функцию-член или свободную функцию (из Википедии):

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

В вашем случае вы хотитереализовать operator== для базового класса, а затем выполнить то, что вы делаете.

Более конкретно это будет выглядеть так:

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
...