仮想代入演算子を実装して遊んでいるうちに、面白い振る舞いで終了しました。 g ++ 4.1,4.3およびVS 2005は同じ動作を共有しているため、コンパイラの不具合ではありません。仮想割り当てが同じ署名の他の仮想関数と異なる動作をするのはなぜですか?
基本的に、仮想演算子=は、実際に実行されているコードに関して他の仮想関数とは異なる動作をします。
struct Base {
virtual Base& f(Base const &) {
std::cout << "Base::f(Base const &)" << std::endl;
return *this;
}
virtual Base& operator=(Base const &) {
std::cout << "Base::operator=(Base const &)" << std::endl;
return *this;
}
};
struct Derived : public Base {
virtual Base& f(Base const &) {
std::cout << "Derived::f(Base const &)" << std::endl;
return *this;
}
virtual Base& operator=(Base const &) {
std::cout << "Derived::operator=(Base const &)" << std::endl;
return *this;
}
};
int main() {
Derived a, b;
a.f(b); // [0] outputs: Derived::f(Base const &) (expected result)
a = b; // [1] outputs: Base::operator=(Base const &)
Base & ba = a;
Base & bb = b;
ba = bb; // [2] outputs: Derived::operator=(Base const &)
Derived & da = a;
Derived & db = b;
da = db; // [3] outputs: Base::operator=(Base const &)
ba = da; // [4] outputs: Derived::operator=(Base const &)
da = ba; // [5] outputs: Derived::operator=(Base const &)
}
効果は、仮想オペレータが=介して呼び出されたときにオペレータの基本バージョンを呼び出すことにより、同じシグネチャ([0] [1]と比較して)を有する任意の他の仮想関数とは異なる挙動を有することですbase参照([2])を介して呼び出されたとき、またはlvalueまたはrvalueのいずれかがBase参照であり、もう一方がBase参照であるときに、正規の仮想関数として実行されている間に、実際の派生オブジェクト([1])または派生参照派生参照([4]、[5])。
この奇妙な動作には分かりやすい説明がありますか?ここで
にあります。ここでの推測はありません。ルールは非常に厳しいものです。 – MSalters
ありがとう、実際の答えは(すでに3人が投稿したように)コンパイラ生成演算子= Derivedクラスのために暗黙的にBase :: operator =を呼び出すということです。私はこれを「受け入れられた答え」として最初のものとしてマークしています。 –
'a = static_cast (b);'は、Cスタイルのキャストを避ける方法です(誤って再解釈キャストを行う危険があります) –