2012-02-07 12 views
31

Considere una jerarquía de clases donde A es la clase base y B deriva de A.¿Por qué el constructor de copia implícita llama al constructor de copia de la clase base y el constructor de copia definido no?

Si el constructor de copia no está definido en B, el compilador sintetizará uno. Cuando se invoca, este constructor de copia llamará al el constructor de copia de la clase base (incluso el sintetizado, si el usuario no lo ha proporcionado).

#include <iostream> 

class A { 
    int a; 
public: 
    A() { 
     std::cout << "A::Default constructor" << std::endl; 
    } 

    A(const A& rhs) { 
     std::cout << "A::Copy constructor" << std::endl; 
    } 
}; 

class B : public A { 
    int b; 
public: 
    B() { 
     std::cout << "B::Default constructor" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    std::cout << "Creating B" << std::endl; 
    B b1; 
    std::cout << "Creating B by copy" << std::endl; 
    B b2(b1); 
    return 0; 
} 

Salida:

Creating B 
A::Default constructor 
B::Default constructor 
Creating B by copy 
A::Copy constructor 

Si el usuario define su propio constructor de copia en B, cuando se invoca, este constructor de copia llamará el constructor base por defecto de clase, a menos que una llamada a el constructor de copia de la clase base está explícitamente presente (por ejemplo, en la lista de inicialización).

#include <iostream> 

class A { 
    int a; 
public: 
    A() { 
     std::cout << "A::Default constructor" << std::endl; 
    } 

    A(const A& rhs) { 
     std::cout << "A::Copy constructor" << std::endl; 
    } 
}; 

class B : public A { 
    int b; 
public: 
    B() { 
     std::cout << "B::Default constructor" << std::endl; 
    } 
    B(const B& rhs) { 
     std::cout << "B::Copy constructor" << std::endl; 
    } 
}; 

int main(int argc, const char *argv[]) 
{ 
    std::cout << "Creating B" << std::endl; 
    B b1; 
    std::cout << "Creating B by copy" << std::endl; 
    B b2(b1); 
    return 0; 
} 

Salida:

Creating B 
A::Default constructor 
B::Default constructor 
Creating B by copy 
A::Default constructor 
B::Copy constructor 

Mi pregunta es, ¿por qué no el definido por el usuario constructor de copia llamar al constructor de copia clase base como un comportamiento por defecto?

+2

Si fuera así por defecto, ¿cómo especificaría el caso en el que no desea que eso suceda? – PlasmaHH

+0

@PlasmaHH 'ParentClass()' en la lista de inicializadores. Eso todavía sería bastante inconsistente y confuso, creo. –

+0

@MarkB: De hecho, esperaba que llegara a la misma conclusión al pensar en ello ... – PlasmaHH

Respuesta

7

Así es como se define el constructor de copia implícita (no tendría sentido llamar al valor predeterminado). Tan pronto como defina cualquier constructor (copia u otro), su comportamiento automático normal es llamar al constructor padre predeterminado, por lo que sería incoherente cambiarlo para un constructor específico definido por el usuario.

1

La respuesta simple (posiblemente trillada) es porque no se lo contó. Como está escribiendo el constructor de copia derivado, controla completamente cómo se comporta. No especificó una llamada a la base y el compilador genera código para inicializar la clase base llamando al constructor predeterminado de las clases base.

8

Todos los constructores secundarios de base llaman al constructor principal por defecto. Así es como se define el estándar. Como usted ha señalado si quería la clase base B a llamar constructor de copia de una que tiene que pedirlo explícitamente

#include <iostream> 

class A { 
int a; 
public: 
A() { 
    std::cout << "A::Default constructor" << std::endl; 
} 

A(const A& rhs) { 
    std::cout << "A::Copy constructor" << std::endl; 
} 
}; 

class B : public A { 
int b; 
public: 
B() { 
    std::cout << "B::Default constructor" << std::endl; 
} 
B(const B& rhs):A(rhs) { 
    std::cout << "B::Copy constructor" << std::endl; 
} 
}; 

int main(int argc, const char *argv[]) 
{ 
std::cout << "Creating B" << std::endl; 
B b1; 
std::cout << "Creating B by copy" << std::endl; 
B b2(b1); 
return 0; 
} 

Esto es así porque el compilador no puede saber para cada constructor diferente, que Constuctor del padre debe ser llamado y, por lo tanto, tenemos los constructores por defecto Para todos los demás tiene que declararlos explícitamente.

+5

'Todos los constructores secundarios de base llaman al constructor padre por defecto. ... ... excepto el constructor de copia implícito :)! –

+0

El constructor de copia implícita es un nombre explícito para una operación más primitiva proporcionada por el compilador, copia bit a bit de la fuente al destino. IMO es solo un nombre elegante. – shakthi

Cuestiones relacionadas