我在覆盖基类 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 {}
这是问题的解决方案还是我在这里遗漏了什么?
谢谢
答案 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&)
,并检查那里的错误情况。
不过这可能不是一个好主意。平等通常对类层次结构没有意义。完全省略比较,或使其非虚拟并仅在子类中定义通常是更好的主意。