2

次のコード(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)の関数'='がない場合、ランタイムは派生オブジェクトにそのような署名が含まれているかどうかを調べ始めますか?

4

1 に答える 1

3

過負荷の解決は、静的タイプを使用して行われます。オーバーロードが選択されると、動的タイプを使用して、使用される関数のオーバーライドされたバージョンが決定されます。それぞれの結果を説明しましょう:

//Every object is a D object, so in
//each case, we expect the virtual calls
//to dispatch to the D version.

//lhs: D, rhs: D, so we expect
//D::operator=(D const&)
cout << "d = d2:   "; d = d2;

//lhs: D, rhs: B, so we expect
//D::operator=(B const&)
cout << "d = b2:   "; d = b2;

//lhs: B, rhs: B, so we expect
//B::operator=(B const&).
//This is virtual, and has been overridden
//in D, so the D version gets called.
cout << "b = b2:   "; b = b2;

//lhs: B, rhs: D, so we expect
//B::operator(D const&).
//This does not exist, so the closest match is used:
//B::operator(B const&). (This is a legal match, 
//because D is a subclass of B).
//This is virtual, and has been overridden
//in D, so the D version gets called.
cout << "b = d2:   "; b = d2;
于 2013-03-02T22:03:39.423 に答える