(我在最后添加了一个更简单的解决方案,它简单地假设如果两个对象的动态类型不同,则相等性应该为假。)
内部operator==
派生不会覆盖operator==
内部基础。它们有不同的签名,一个接受 Base& 作为other
,另一个接受 Derived&。它们必须相同才能覆盖工作(您可以稍微更改返回类型,但不能更改参数类型。)
一种解决方案是使用double dispatch解决此问题。real_comparator
您定义了一个实际执行比较工作的方法(或者可能是一个自由函数) 。有四个版本real_comparator
,Base 和 Derived 类各有两个。
当我们这样做时a==b
,我们希望将两个变量的动态类型都考虑在内。a==b
被编译器重写为a.operator==(b)
,因此,默认情况下,只有a
参与多态性。我们想改变它,以便可以激活两个变量(以及所有四种可能性)。
诀窍在于return other.real_comparator(*this);
struct Derived;
struct Base {
virtual bool real_comparator(Base const& /*other*/) const {
std::cerr << "Base == Base?" << std::endl;
return false;
}
virtual bool real_comparator(Derived const& /*other*/) const {
std::cerr << "Base == Derived?" << std::endl;
return false;
}
virtual bool operator==(Base const& other) const {
return other.real_comparator(*this);
}
};
struct Derived : Base {
virtual bool real_comparator(Base const& /*other*/) const override {
std::cerr << "Derived == Base?" << std::endl;
return false;
}
virtual bool real_comparator(Derived const& /*other*/) const override {
std::cerr << "Derived == Derived?" << std::endl;
return false;
}
virtual bool operator==(Base const& other) const override {
return other.real_comparator(*this);
}
};
我认为这段代码可以稍微简化一下,特别是如果你有一条规则说“如果两个对象是不同的动态类型,比较的结果总是错误的”,或者类似的东西。
更简单的解决方案是可能的,但这取决于您要解决的问题。假设,如果两个对象具有不同的动态类型,那么比较应该返回 false:
#include<typeinfo> // We need this for typeid to work
using namespace std;
struct Base {
virtual bool operator==(Base const& other) const {
if(typeid(other) != typeid(*this))
return false;
else
cout << "A pair of Bases" << endl;
return true; // replace this with code to compare two Base objects
}
};
struct Derived : Base {
virtual bool operator==(Base const& other) const override {
if(typeid(other) != typeid(*this))
return false;
else
cout << "A pair of Deriveds" << endl;
// So 'other' is actually a Derived.
const Derived * derived_pointer = dynamic_cast<const Derived*>(&other);
// Now, we can compare 'this' to 'derived_pointer', both pointers to Derived
return derived_pointer == this; // replace this with code to compare two Derived
}
};
这应该是正确的,但也许可以在某些方面进行改进。任何反馈表示赞赏?