2010-12-08 16 views
9

Estoy jugando solo para entender los indicadores inteligentes y tratando de hacer la mía, pero me encuentro con una situación que no entiendo completamente. Aquí está el código:¿Por qué el operador de asignación llama al constructor?

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

El código se compila y en la línea de holder = b; se llama al constructor de la clase Holder. Pensé que el compilador daría un error. No es el operador de assesment, pero ¿por qué está llamando al constructor?

+0

'Holder' tiene dos constructores, que uno que se llama? – suszterpatt

+0

@suszterpatt: Titular (T * tt) –

Respuesta

13

holder = b intenta asignar de b a Holder. b es del tipo A*, y holder es del tipo Holder<A>.

La plantilla Holder define la asignación de otro ejemplo del mismo tipo Holder, por lo que el compilador busca una conversión A*-Holder<A>. Encuentra el constructor y lo usa.

Los constructores que pueden tomar exactamente un argumento se pueden usar para las conversiones implícitas, a menos que los etiquete con la palabra clave explicit.

+0

+1 para "explícito". Gracias. –

0

Tiene un constructor tomando una T *. Su tarea tiene un puntero rhs, por lo que construye un temp-obj con ese puntero como argumento y lo asigna al titular.

4

Se invocan el constructor y el operador de asignación. Puede verificar esto imprimiendo algo en operator =.

Esto ocurre porque operator = se define para tomar un const Holder &, pero b es del tipo A *. Entonces, primero se llama al constructor Holder(T *) para crear un objeto temporal, luego este objeto se asigna a holder a través de operator =.

Si define un operator =(const T *), solo se llamará al operador de asignación.

1

no veo una versión del operador de asignación que tiene un lado derecho de A *

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. 
Cuestiones relacionadas