qué - que es un destructor en c++
¿Por qué el constructor de copia implícita llama al constructor de copia de la clase base y el constructor de copia definido no? (3)
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.
Considere una jerarquía de clases donde A
es la clase base y B
deriva de A
Si el constructor de copia no está definido en B
, el compilador sintetizará uno. Cuando se invoca, este constructor de copia llamará al 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á al constructor predeterminado de la clase base , a menos que una llamada al 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é el constructor de copia definido por el usuario no llama al constructor de copia de la clase base como comportamiento predeterminado?
La respuesta simple (posiblemente trillada) es porque no se lo dijiste. 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.
Todos los constructores secundarios de base llaman al constructor padre por defecto. Así es como se define el estándar. Como usted señaló si quería que la clase base B llamara al constructor de copias de A, 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 qué constuctor del padre debe ser llamado y, por lo tanto, tenemos los constructores por defecto. Para todos los demás, usted debe declararlos explícitamente.
Salida:
Creating B A::Default constructor B::Default constructor Creating B by copy A::Copy constructor B::Copy constructor