О конструкторах по умолчанию и копировании

0

Рассмотрим следующий код:

#include <iostream>

struct A
{
    A() {} // Can't be commented
    A( const A& other ) =delete;
    int i;
};

struct B : public A
{
    B( int j ) { this->i = j; }
    B( const B& other ) { this->i = other.i; }
};

int main()
{
    B b(42);
    std::cout << b.i << std::endl;
}

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

Теги:
inheritance
copy-constructor

3 ответа

2
Лучший ответ

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

Когда вы закомментируете пустой конструктор A, конструкторы B не смогут его назвать.

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

  • 0
    Но считается ли удаление конструктора определением?
  • 0
    @ LuchianGrigore да, ты прав. Я исправил это утверждение.
Показать ещё 4 комментария
5

Поскольку этот конструктор:

B( int j ) { this->i = j; }

инициализируется по умолчанию B A -объект. Он делает эквивалент этого:

B( int j ) : A() { this->i = j; }

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

  • 0
    Я был не из тех, кто понизил голос, извините за это. Это действительно не отвечает на мой вопрос, хотя; если я прокомментирую оба конструктора в A, то смогу скомпилировать .. Отсюда мой вопрос "что меняется, когда я отключаю его конструктор копирования"?
  • 0
    @ Sh3ljohn посмотри мои изменения.
Показать ещё 1 комментарий
1

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

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

  • 0
    «Как только вы объявите конструктор в классе (и объявлен удаленный, он просто ... удален), компилятор не сгенерирует для вас никакого другого конструктора». - неправильно.
  • 0
    Действительно, есть конструктор перемещения. Я забыл дефолт
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню