次のコード(C ++ FAQ 24.11から)は、仮想代入演算子のオーバーロードとオーバーライドを実装しています。
#include <iostream> using namespace std; class B{ public: virtual ~B() throw(); virtual B& operator= (const B& b) throw(); }; B::~B() throw(){} B& B::operator= (const B& b) throw() { cout << "B::operator=(const B&)\n"; return *this; } class D : public B{ public: virtual D& operator= (const B& b) throw(); D& operator= (const D& d) throw(); }; D& D::operator= (const B& b) throw() {cout << "D::operator= (const B&)\n"; return *this;} D& D::operator= (const D& d) throw() {cout << "D::operator= (const D&)\n"; return *this;} void sample(D& d, B& b, D& d2, B& b2){ cout << "d = d2: "; d = d2; cout << "d = b2: "; d = b2; cout << "b = b2: "; b = b2; cout << "b = d2: "; b = d2; } int main() { D d, b, d2, b2; sample(d,b,d2,b2); }
出力は次のようになります。
- d = d2:D :: operator =(const D&)
- d = b2:D :: operator =(const B&)
- b = b2:D :: operator =(const B&)
- b = d2:D :: operator =(const B&)
それは言う:
「コンパイラーはパラメーターの静的タイプに基づいて呼び出すオーバーライドを解決するため、最初の代入はDをとる代入演算子を呼び出す唯一の代入であり、他のすべてはBをとる代入演算子を呼び出すことになります。」
と
"sample()のbの実際のクラスはDであるため、最後の2つの呼び出しはオーバーライド(D :: operator =(const B&))に解決されます。bが実際にBであった場合、最後の2つの呼び出しは( B :: operator =(const B&)) "
私は少し混乱しています。最初の段落では、コンパイラがパラメータの静的型を調べて、使用されている(オーバーロードされた?)関数呼び出しを判別していると述べています。引数が渡されたときに、最後のケースでBパラメータ型の演算子が呼び出されるのはなぜですか。 、d2はD& d2
、sample()で型として宣言されていますか?
編集以下の回答を参照すると、B :: =(D)のリクエストがどのようにD :: =(B)になるかわかりません。別のサブクラスEがあった場合はどうなりますか?E :: =(B)ではなくD :: =(B)が呼び出されるのはなぜですか?Bにパラメーター(D)の関数'='がない場合、ランタイムは派生オブジェクトにそのような署名が含まれているかどうかを調べ始めますか?