operator== 标记为“覆盖”,但不覆盖

时间:2021-07-02 12:39:53

标签: c++ operator-overloading c++14

我在覆盖基类 operator== 时遇到问题。这是代码。

#include <iostream>
#include <vector>

using namespace std;

template <typename T>
class IClient {
  virtual const std::vector<T>& getID() = 0;
  virtual bool isEqual(const std::vector<T>& anotherID) = 0;
  virtual bool operator==(const IClient& anotherClient) = 0;
};

class SeviceClient : public IClient<int8_t> {
  const std::vector<int8_t> ID;

 public:
  SeviceClient(const std::vector<int8_t>& ID) : ID(std::move(ID)) {}
  SeviceClient(const std::vector<int8_t>&& ID) : ID(std::move(ID)) {}

  const std::vector<int8_t>& getID() override {
      return ID;
  }
  bool isEqual(const std::vector<int8_t>& anotherID) override {
      return true;
  }
  bool operator==(const SeviceClient& anotherClient) override {
      return true;
  }
};

它抱怨

 error: 'bool SeviceClient::operator==(const SeviceClient&)' marked 'override', but does not override

当我将函数转换为时,编译器看起来很高兴

bool operator==(const IClient<int8_t>& anotherClient) override {}

这是问题的解决方案还是我在这里遗漏了什么?

谢谢

3 个答案:

答案 0 :(得分:1)

ServiceClient 和 IClient 是不同的类型。 因此, bool SeviceClient::operator==(const SeviceClient&) 没有基本声明。

答案 1 :(得分:1)

您必须了解 C++ 有可能重载函数。 因此,要识别假设被调用的函数,不仅函数名必须匹配,而且参数的类型也必须匹配。当然还有隐式转换,可以调整参数以匹配函数的参数类型,但请注意,如果有多个同名函数,则隐式转换可能会导致歧义。

如果你使用多态,那么你必须记住子类应该是可用的,因为它只是父类。持有基类指针的人不应该注意到它实际上是一个子类。

因此,当您覆盖虚函数时,参数类型必须非常精确,所以一切都没有歧义。

我怀疑您需要静态多态性和 CRTP 而不是动态多态性。所以是这样的:

getMinutes

答案 2 :(得分:1)

这个问题有两个方面。一,这种设计违反了 C++ 的哪些规则?第二,为什么C++有这样的规则?

第一个很简单。您可以通过具有完全相同参数列表的函数来覆盖函数。由于 (const IClient& anotherClient)(const SeviceClient& anotherClient) 不完全相同,因此不会发生覆盖。案件已结。

第二个涉及更多。为了理解它,让我们使用一个更熟悉的类层次结构。有class Animal,还有class Dog : public Animal,还有class Cat : public Animal

bool Animal::operator==(const Animal&) 告诉我们什么?它告诉我们可以将一种动物与另一种动物进行比较。特别是,我们可以将狗与狗、猫与猫、狗与猫、老鼠与蝙蝠、鱼与蚊子、土豚与霸王龙进行比较。 class Animal 使您成为我们的承诺。如果我们有两个 Animal 对象,我们可以比较它们。

现在,重写此运算符的函数应该履行承诺。 bool Dog::operator==(const Dog&) 会这样做吗?不,它实现了一个更窄的承诺:这个 Animal(恰好是一个 Dog)可以与一个 Dog 进行比较。实现这个狭隘的应许是否合法?绝对地。假装这个功能也实现了广泛的承诺,即能够比较任何两只动物,是否合法?绝对不。所以我们可以声明这个函数,但不能声称它覆盖了 Animal 相等运算符。

如果有一条规则允许我们声明,会发生什么?

Dog d;
Cat c;
Animal& da = d;
Animal& ca = c;
std::cout << (da == ca);

这个程序片段必须编译,因为每一行都是有效的(根据我们的幻想规则),但是它应该做什么?没有代码可以比较狗和猫!

有些语言会说“好吧,没什么大不了的,我们只会抛出一个运行时错误”。 C++ 不这样做。如果你想让上面的代码抛出运行时错误,你应该自己编写抛出运行时错误的代码。这意味着用 bool Animal::operator==(const Animal&)bool Dog::operator==(const Animal&) 覆盖 bool Cat::operator==(const Animal&),并检查那里的错误情况。

不过这可能不是一个好主意。平等通常对类层次结构没有意义。完全省略比较,或使其非虚拟并仅在子类中定义通常是更好的主意。