我有这段代码:
class ISerializable
{
public:
virtual bool operator==(const ISerializable* /*value*/) const { return false;};
virtual bool operator!=(const ISerializable* /*value*/) const { return true;};
};
class Point2I : public ISerializable
{
public:
bool operator==(const Point2I& value)
{
return (x == value.x && y == value.y);
}
bool operator!=(const Point2I& value)
{
return !(*this == value);
}
public:
int x;
int y;
};
class Coordinate : public ISerializable
{
public:
virtual bool operator==(const Coordinate& value) const;
virtual bool operator!=(const Coordinate& value) const;
};
导致我- wooverloading -virtualGCC编译器的警告。
我理解这个警告,因为在Point2I中的函数声明隐藏虚函数isserializable.但我不确定是否只是缺少const在Point2I可能导致此警告。
你能帮我理解一下是不是const是什么引起了这个警告还是别的什么?来自gcc的警告描述没有特别提到任何内容。
更新:
我找到了另一个类坐标在我的代码库中,它已经覆盖了这个,GCC没有为此抛出警告。唯一的区别是Point2I协调和我没有将声明为虚的const在Point2I. 它看起来只是const隐藏基类声明。
如果是const导致这个警告或其他什么?
我想说它是别的,也就是说你实际上并没有重写基类方法,即使你添加了const
。
参数const ISerializable*
和const Point2I&
不一样。
一种解决方案是覆盖基类方法,使用const ISerializable&
作为参数,并在覆盖的方法中强制转换:
class ISerializable {
public:
// add virtual destructor if you need to delete objects through
// base class pointers later:
virtual ~ISerializable() = default;
virtual bool operator==(const ISerializable&) const { return false; }
virtual bool operator!=(const ISerializable&) const { return true; }
};
class Point2I : public ISerializable {
public:
bool operator==(const ISerializable& value) const override {
auto rhs = dynamic_cast<const Point2I*>(&value);
// rhs will be nullptr if the cast above fails
return rhs && (x == rhs->x && y == rhs->y);
}
bool operator!=(const ISerializable& value) const override {
return !(*this == value);
}
private:
int x = 0;
int y = 0;
};
使用例子:
#include <iostream>
class Foo : public ISerializable { // another ISerializable
public:
};
int main() {
Point2I a, b;
std::cout << (a == b) << 'n'; // true - using Point2I::operator==
Foo f;
std::cout << (a == f) << 'n'; // false - using Point2I::operator==
std::cout << (f == a) << 'n'; // false - using ISerializable::operator==
// this makes the default implementation in ISerializable utterly confusing:
std::cout << (f == f) << 'n'; // false - using ISerializable::operator==
}
另一个可能的解决方案是使用CRTP,但如果你想比较从ISerializable<T>
派生的不同类型,这将不起作用:
template<class T>
class ISerializable {
public:
virtual ~ISerializable() = default;
virtual bool operator==(const T&) const = 0;
virtual bool operator!=(const T&) const = 0;
};
class Point2I : public ISerializable<Point2I> {
public:
bool operator==(const Point2I& value) const override {
return (x == value.x && y == value.y);
}
bool operator!=(const Point2I& value) const override {
return !(*this == value);
}
public:
int x;
int y;
};
有两个问题。
第一个是不同类型的参数
在这些函数中参数的指针类型为const ISerializable*
virtual bool operator==(const ISerializable* /*value*/) const { return false;};
virtual bool operator!=(const ISerializable* /*value*/) const { return true;};
,在这些函数中参数的引用类型为const Point2I&
bool operator==(const Point2I& value)
{
return (x == value.x && y == value.y);
}
bool operator!=(const Point2I& value)
{
return !(*this == value);
}
第二个错误是第一个函数是常量成员函数,而第二个函数不是常量成员函数。