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

Рассмотрим иерархию классов, где 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

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

3 ответа

Решение

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

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

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

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

Выход:

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

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

Другие вопросы по тегам