2010-12-08 23 views
9

Akıllı göstergeleri anlamak ve benimkini yapmaya çalışmak için uğraşıyorum ama tam olarak anlamadığım bir durumla karşılaşıyorum. İşte kod:Atama operatörü neden kurucuyu arar?

#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; 
} 

kod derler ve holder = b; hattı üzerinde Holder sınıfının yapıcısı olarak adlandırılır. Derleyici bir hata vereceğini düşündüm. Bu, assingment operatörü değil, neden kurucuyu arıyor?

+0

denir A * bir sağ tarafını alır atama operatörünün bir versiyonunu görmüyorum? – suszterpatt

+0

@suszterpatt: "açık" için tutucu (T * tt) –

cevap

13

holder = b girişimleri b den Holder atanacak. b, A* tipindedir ve holder, Holder<A> tipindedir.

Holder şablon aynı Holder türde başka bir örneği ataması, yani derleyici Holder<A> için A* bir dönüşüm arar. Kurucu bulur ve bunu kullanır. tam olarak bir argüman alabilir

Kurucular explicit anahtar kelime etiketliyorsanız sürece, örtük dönüşümler için kullanılabilir.

+0

+1. Teşekkürler. –

0

T * alan bir kurucunuz var. Atanızın bir rhs işaretçisi vardır, bu nedenle bu gösterici ile argüman olarak bir temp-obj oluşturur ve bunu tutucuya atar.

4

Hem yapıcı hem de atama operatörü çağrılır. operator =’da bir şey yazdırarak bunu kontrol edebilirsiniz.

operator = bir const Holder & almaya tanımlanır Bunun nedeni, ancak b tip A * taşımaktadır. Bu nedenle, önce Holder(T *) yapıcısının geçici bir nesne oluşturması çağrılır, daha sonra bu nesne ile operator = arasında atanır.

Bir operator =(const T *) tanımlarsanız, yalnızca atama operatörü aranır.

1

ben `Holder`, iki oluşturucusu yok hangisinin

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. 
İlgili konular