4

現在C++で遊んでいるので、問題が発生します。以下のコード:

#include        <iostream>

class Base {
public:
  virtual ~Base()                   {}


  virtual Base&         operator=(const Base& o)
  {
    std::cout << "Base operator called" << std::endl;
    return *this;
  }
};

class Derived : public Base {
public:
  virtual ~Derived() {}

  virtual Base&         operator=(const Base& o)

  {
    std::cout << "Derived operator called" << std::endl;
    return *this;
  }
};

int     main(void)
{
  Derived       a;
  Derived       b;
  Base&         c = a;
  Base&         d = b;

  a = b;                        // Base called                                                                                                                                 
  a = static_cast<Base>(b);     // Derived called                                                                                                                              
  a = d;                        // Derived called                                                                                                                              
  c = d;                        // Derived called                                                                                                                              
  return (0);
}

コメントは、私が得た出力を示しています。最後の3つの結果は非常に予測可能ですが、最初の結果は理解できません。

2番目の例(static_cast)に示すように、右のオペランドがBaseクラスの場合、Derived ::operator=が呼び出されます。ただし、g ++(4.5.3-r2、gentoo Linux)は、「Base」クラスを使用する必要があることを理解することに成功しましたが、継承ツリーを下っていません。

したがって、Derived :: operator =が呼び出されるか、g ++が「Derived&Derived :: operator =(const Derived&)」がないと文句を言うことを期待していました。誰かが私にこの振る舞いを説明できますか?ありがとう!

4

1 に答える 1

3

のコピー代入ではないため、コンパイラによって生成されたコピー代入があります。つまりoperator=(Derived &)Derivedクラス内にあります。これは、コードで割り当てを使用する場合、コンパイラがコピー割り当てを生成することを妨げません。Derived::operator=(Base const&)Derived

したがって、この行:

 a = b;  // Base called     

クラス用に生成されたコンパイラを呼び出し、次にoperator=(Derived &)。を呼び出します。したがって、印刷されます。Derivedoperator=(Base const&)Base called

実験:これをDerivedクラスに追加します:

Derived & operator=(Derived const & obj) : Base(obj)
{
   std::cout << "copy-assignment called" << std::endl;
   return *this;
}

今、a=bこれを印刷します:

コピーと呼ばれるベース
-と呼ばれる割り当て   

印刷の順序にも注意してください。

それがあなたの疑問を明らかにすることを願っています。


さて、これ、

a = static_cast<Base>(b);  /// Derived called    

機能的にはこれと同等です:

Base ___generated_tmp = static_cast<Base>(b);
a = ___generated_tmp;

は、のタイプがであるため、をa = ___generated_tmp呼び出します。operator=(Base const&)___generated_tmpBase

そして、あなたがすでに知っているように、残りの2つはかなり明確です。

于 2012-08-27T17:40:00.677 に答える