如何在重写函数中使用子类引用重写纯虚函数

How to override a pure virtual function using a subclass reference in the overriden function

所以我在派生 class 中覆盖纯虚函数时遇到问题。 classes 的实现和声明如下所示:

class Base{
private:
   size_t id;
public:
   virtual bool isEqual(const Base& src) const =0;
};

class Derived: public Base{
private:
    string str;
public:
    virtual bool isEqual(const Derived& src) const override
    {
        return (this->str == src.str);
    }
};

所以当我这样实现它时,我遇到了编译器错误,例如

member function declared with 'override' does not override a base class member function

你能告诉我如何才能做到这一点吗,也许可以解释一下为什么我的版本不起作用。提前致谢!

多态的原理是一个Derived一个Base。如果要覆盖函数,签名必须相同。

解决您的问题的正确方法是将您的替代定义为等同于:

bool Derived::isEqual(const Base & src) const
{
    try
    {
        Derived & d = dynamic_cast<Derived &>(src);
        return (this->str == d.str);
    }
    catch(const std::bad_cast & e)
    {
        // src is not a Derived
        return false;
    }
}

如果你想使用指针,你可以按照下面的方式做同样的事情:

bool Derived::isEqual(const Base * src) const
{
    const Derived * d = dynamic_cast<const Derived*>(src);

    if(d == nullptr) // src is not a Derived*
        return false;
    else
        return (this->str == d->str);
}

当然,它假设您在 Base 中有一个匹配的定义可以覆盖。


@Aconcagua提供的解决方案以更优雅的方式使用了相同的想法。我建议改用他的解决方案。

您不能以这种方式更改函数签名 - 阅读有关 co- and contravariance 的详细信息以及为什么 C++ 不允许函数 参数 (协变 return 类型是允许)。

另一方面,如果另一个对象是通过引用 base 引用的,则根本不会调用覆盖(实际上:重载!)函数:

Derived d1;
Derived d2;
Base& b2 = d2;

d1.isEqual(b2); // how do you imagine the derived version to get called now???

解决方案的关键是 dynamic_cast:

struct Base
{
    virtual ~Base() { }
    virtual bool operator==(Base const& other) = 0;
};

struct Derived : Base
{
    bool operator==(Base const& other) override
    {
        auto o = dynamic_cast<Derived const*>(&other);
        return o && o->str == this->str;
    }
};

注意我把函数重命名为operator==;这在 C++ 中更为自然。这样,您可以在上面的示例中与以下内容进行比较:

bool isEqual = d1 == b2;

编辑:

The teacher told us that we must not overload operator

好吧,然后恢复重命名...实际上,运算符与其他任何函数一样都是普通函数,只是调用语法不同(实际上:存在替代变体,您总是可以调用 d1.operator ==(d2), 也是).