Подтвердить что ты не робот

Почему конструктор неявных копий вызывает конструктор экземпляра базового класса и нет конструктора заданий?

Рассмотрим иерархию классов, где A - базовый класс, а B - A.

Если конструктор копирования не определен в B, компилятор будет его синтезировать. При вызове этот конструктор копирует вызов конструктор копирования базового класса (даже синтезированный, если ни один из них не был предоставлен пользователем).

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

Вывод:

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

Если пользователь определяет свой собственный конструктор копирования в B, при вызове этот конструктор копирования вызовет конструктор по умолчанию базового класса, если явно не встречается вызов конструктора копии базового класса ( например, в списке инициализации).

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

Вывод:

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

Мой вопрос в том, почему пользовательский конструктор копирования не вызывает конструктор копии базового класса как поведение по умолчанию?

4b9b3361

Ответ 1

Это точно так же, как определено конструктор неявных копий (это не имеет смысла вызвать значение по умолчанию). Как только вы определяете какой-либо конструктор (копия или иное), его обычное автоматическое поведение заключается в вызове родительского конструктора по умолчанию, поэтому было бы непоследовательно изменять его для одного конкретного определяемого пользователем конструктора.

Ответ 2

Все базовые дочерние конструкторы называют родительский конструктор по умолчанию. Так определяется стандарт. Как вы указали, хотите ли вы, чтобы базовый класс B вызывал конструктор копирования, вы должны явно запросить его

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

Это происходит потому, что компилятор не может знать для каждого другого конструктора, который должен быть вызван конструктором родителя, и, следовательно, у нас есть конструкторы по умолчанию. Для всех остальных вам нужно явно указать их.

Ответ 3

Простой (возможно, банальный) ответ заключается в том, что вы этого не сказали. Поскольку вы пишете производный экземпляр копии, вы полностью контролируете, как он себя ведет. Невозможность указать вызов базы, а компилятор генерирует код для инициализации базового класса, вызвав конструктор по умолчанию базовых классов.