Как я должен написать конструктор копирования для инициализации другого объекта?

#c #oop #destructor

#c #ооп #деструктор

Вопрос:

Скажем, в качестве упрощенного примера у меня есть объект класса House, в котором также есть объект Kitchen.

Вот файл заголовка:

 class Kitchen {
   private:
       int width;
       int height;
       int length;
   public:
       Kitchen(int width, height, length); // default constructor
};

class House {
   private:
       int houseId;
       Kitchen newKitchen;
   public:
       House(Kitchen newKitchen, int houseId); // default constructor
       Houseamp; operator=(House constamp; other); // copy assignment
       House(House constamp; other); // copy constructor
       ~House(); // destructor
};
 

Копирование houseId отлично работает в функции назначения копирования. Но я получаю сообщение об ошибке, относящееся к House::House(House constamp; other) { *this = other; } следующему:

 error: constructor for 'House' must explicitly initialize the member 'newKitchen' which does not have a default constructor
 

в чем я не уверен, поскольку я думал, что мое объявление конструктора по умолчанию охватывает это?

Комментарии:

1. Если все в членах вашего класса тривиально копируется, лучший выбор — вообще не писать конструктор копирования. Компилятор генерирует его по умолчанию.

2. … и Kitchen(int width, height, length); и House(Kitchen newKitchen, int houseId); не являются конструкторами по умолчанию.

3. Примечание: обычно проще, чтобы оператор присваивания использовал конструктор копирования, а не наоборот. Когда у вас есть члены или базовые классы, которые требуют инициализации, присваивание не может его сократить.

Ответ №1:

Во-первых, ваш «конструктор по умолчанию» в Kitchen не является конструктором по умолчанию, это определяемый пользователем конструктор. Он должен инициализировать элементы, а также я бы повторно включил копирование и перемещение, следуя правилу пяти.

 class Kitchen {
   private:
       int width;
       int height;
       int length;
   public:
       // Use member initialization list
       Kitchen(int _width, int _height, int _length) : width(_width), height(_height), length(_length) {}

       // Rule of 5
       Kitchen(Kitchen constamp;) = default;
       Kitchenamp; operator=(Kitchen constamp;) = default;
       Kitchen(Kitchenamp;amp;) = default;
       Kitchenamp; operator=(Kitchenamp;amp;) = default;
};
 

Затем позже вы House сможете использовать этот пользовательский конструктор аналогичным образом

 House(Kitchen _newKitchen, int _houseId) : houseId(_houseId), newKitchen(_newKitchen) {}
 

Обратите внимание, что ваш Kitchen может быть просто агрегированным типом POD, чтобы избежать проблем

 class Kitchen
{
public:
    int width;
    int height;
    int length;
}
 

Это будет следовать «правилу нуля» и будет по умолчанию конструируемым, агрегируемым инициализируемым, копируемым и перемещаемым. То же самое будет следовать и для вашего House класса.

Комментарии:

1. Привет, большое спасибо за ваш комментарий. Я попытался реализовать то, что вы предложили, и я все еще получаю те же ошибки. Я создал список инициализаторов для House и Kitchen в своих пользовательских конструкторах

2. @mlan Если вы реализовали то, что предложил Кори, вы не можете получить ту же ошибку. ДЕМОНСТРАЦИЯ