наследование — переопределение оператора для использования производного класса в переполнении стека

Я пытаюсь переопределить оператор виртуального сравнения в подклассе, но получаю ошибку компилятора, говорящую, что производный класс не реализует виртуальный оператор базового класса.

У меня есть ощущение, что это связано с тем, что мой производный оператор не использует тип аргумента базового класса.

Упрощенная версия выглядит следующим образом:

struct Base {
virtual bool operator ==(const Base) const;
};

struct Derived : Base {
bool operator ==(const Derived) const {
// implementation goes here
}
};

Есть ли способ для меня, или я должен сделать проверку типа в Derived реализация, чтобы увидеть, если это правильный тип?

3

Решение

У меня есть ощущение, что это связано с тем, что мой производный оператор
не использует тип аргумента базового класса.

Точно так. Базовый класс должен принимать const ссылка (чтобы он мог иметь динамический тип Derivedи затем вы объявляете переопределение как:

bool operator ==(const Base& rhs) const {
const auto pRhs = dynamic_cast<const Derived*>(&rhs);
if (pRhs == nullptr)
{
return false;  // Not a derived.  Cannot be equal.
}
// Derived/Derived implementation goes here
}

Но будьте осторожны: такой виртуальный оператор сравнения очень легко ошибиться. Вам нужен хороший мотивирующий пример, чтобы сделать это так. В частности, если вы напишите:

Derived d;
Base b;
if (d == b)  // All is well - derived override called, and returns false.

if (b == d) // Uh-oh!  This will call the *base* version.  Is that what you want?

Также:

Derived d;
DerivedDerived dd;

if (d == dd) // Did you want to use the DerivedDerived comparison?
3

Другие решения

В реализации Derived необходимо ввести проверку того, что параметр имеет ожидаемый тип.

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

struct Base {
virtual int compare(const Base& source) const { return 0; }

bool operator ==(const Base& source) const
{ return compare(source) == 0; }
};

struct Derived : Base {
int compare(const Base& asource) const override
{ const Derived* source = dynamic_cast<const Derived*>(&asource);
int result = -2;
if (source) { ... result = ...; }
return result;
}

// redefinition to force the expected/right signature at this level
bool operator==(const Derived& source) const
{ return compare(source) == 0; }
};
2

По вопросам рекламы [email protected]