2010-12-08 7 views
9

私はちょうどスマートなポインタを理解し、私のことをしようとするの周りに遊んでいるが、私は完全に理解していない状況に遭遇する。ここでは、コードは次のようになります。代入演算子の呼び出しコンストラクタはなぜですか?

#include <iostream> 
template <class T> 
class Holder 
{ 
private: 
     T * obj; 
public: 
     Holder(T * tt) : obj(tt) 
     { 
       std::cout << "ctor : " << tt->dummy << std::endl; 
     } 
     T * operator ->() 
     { 
       return obj; 
     } 
     operator bool() 
     { 
       return obj; 
     } 
     T * const get() const 
     { 
       return obj; 
     } 
     void reset() {swap(0);} 
     void swap(T * other) 
     { 
       obj = other; 
     } 
     Holder & operator = (const Holder& holder) 
     { 
       obj = holder.get(); 
       return *this; 
     } 
     Holder(const Holder & holder) : obj(holder.get()) {} 
}; 

class A 
{ 
public: 
     int dummy; 
     A(int a) : dummy(a) {} 
}; 

int main() 
{ 
     A * a = new A(1); 
     Holder<A> holder(a); 
     A * b = new A(2); 
     holder = b; 

     std::cout << holder->dummy << std::endl; 

     return 0; 
} 

コードがコンパイルされ、holder = b;の行にHolderクラスのコンストラクタが呼び出されます。私はコンパイラがエラーを与えるだろうと思った。それはassingment演算子ではありませんが、なぜそれがコンストラクタを呼び出すのですか?

+0

と呼ばれている*の右側を取る代入演算子のバージョンが表示されませんか? – suszterpatt

+0

@suszterpatt:ホルダー(T * tt) –

答えて

13

holder = bbからHolderへの割り当てを試みます。 bはタイプA*であり、holderはタイプHolder<A>です。

Holderテンプレートは同じHolderタイプの別のインスタンスから割り当てを定義するので、コンパイラは、Holder<A>からA*から変換探し。それはコンストラクタを見つけ、それを使用します。正確に一つの引数を取ることが

コンストラクタは、あなたがexplicitキーワードでそれらをタグ付けない限り、暗黙の型変換のために使用することができます。

+0

+1は「明示的」です。ありがとう。 –

0

あなたはT *を取るコンストラクタを持っています。 あなたのassigmentにはrhsポインタがあるので、そのポインタを引数としてtemp-objを構築し、これをホルダーに割り当てます。

4

コンストラクタと代入演算子の両方が呼び出されます。これは、operator =に何かを印刷することで確認できます。

これは、operator =const Holder &となるように定義されていますが、bは、タイプがA *であるために発生します。最初にHolder(T *)コンストラクタが呼び出されて一時オブジェクトが作成されると、このオブジェクトはholderからoperator =に割り当てられます。

operator =(const T *)を定義すると、代入演算子のみが呼び出されます。

1

私は `Holder`は、2つのコンストラクタを持っているものを

A*  a  = new A(1); 
    Holder<A> holder(a); 
    A*  b   = new A(2); 

    // assigning object of type A* to Holder<A> 
    holder = b; 

    // No appropriate assignment operator provide. 
    // But a constructor is available to convert RHS parameter to correct type. 
    // So compiler generates the following code: 

    holder = Holder<A>(b); 

    // There is an appropriate assignment operator for this. 
    // So it compiles. 
関連する問題