4

我试图覆盖子类中的虚拟比较运算符,但我收到编译器错误,说派生类没有实现基类的虚拟运算符。

我感觉这与我的派生运算符不使用基类的参数类型有关。

一个简化的版本如下:

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

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

我有办法做到这一点,还是我必须在Derived实现中进行类型检查以查看它是否是正确的类型?

4

2 回答 2

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?
于 2016-10-31T18:07:58.440 回答
2

您必须在派生实现中键入检查参数是否具有预期的类型。

对于运算符,您可能更喜欢定义一个虚拟标准方法,然后通过调用此方法来实现您的运算符。这避免了对操作员来说意外或太大的签名。

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; }
};
于 2016-10-31T18:08:54.390 回答