( 2 つのオブジェクトの動的な型が異なる場合、等価性は false であるという単純な仮定を行う、より単純なソリューションを最後に追加しました。 )
内部の派生は、内部のベースoperator==
をオーバーライドしません。operator==
には異なる署名があり、1 つは Base& を as として受け入れ、もう 1 つはother
Derived& を受け入れます。オーバーライドが機能するには、それらが同一である必要があります (戻り値の型を少し変更できますが、パラメーターの型は変更できません)。
解決策の 1 つは、二重ディスパッチでこれを修正することです。real_comparator
実際に比較作業を行うメソッド (またはおそらくフリー関数) を定義しました。real_comparator
には、Base クラスと Derived クラスのそれぞれに 2 つずつ、合計 4 つのバージョンがあります。
を行うときはa==b
、両方の変数の動的タイプを考慮に入れる必要があります。a==b
はコンパイラによって として書き換えられるa.operator==(b)
ため、デフォルトではa
、ポリモーフィズムに参加するのは だけです。これを変更して、両方の変数 (したがって、4 つの可能性すべて) をアクティブにできるようにします。
トリックは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);
}
};
このコードは、特に「2 つのオブジェクトの動的タイプが異なる場合、比較の結果は常に false になる」などのルールがある場合は、少し簡略化できると思います。
より簡単な解決策が可能ですが、解決したい問題によって異なります。2 つのオブジェクトの動的な型が異なる場合、比較で 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
}
};
これは正しいはずですが、何らかの方法で改善できる可能性があります。フィードバックをいただければ幸いです。