Pregunta ¿Por qué el constructor de copia implícita llama al constructor de copia de la clase base y el constructor de copia definido no?


Considere una jerarquía de clase 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 copia llamará el constructor de copia de clase base (incluso el sintetizado, si ninguno ha sido proporcionado por el usuario).

#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 copia llamará el 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?


32
2018-02-07 14:42


origen


Respuestas:


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.


7
2018-02-07 14:49



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 el constructores por defecto Para todos los demás tienes que declararlos explícitamente.


8
2018-02-07 14:54



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.


1
2018-02-07 14:50