Здравствуйте!
Ваш вопрос связан с особенностями работы с классами и конструкторами в C++. Давайте разберем проблему, с которой вы столкнулись.
Ошибка, которую вы видите, связана с тем, как компилятор C++ управляет инициализацией объектов и копированием значений.
### Почему возникает ошибка?
1. **Конструктор класса**: У вас есть класс `NumberBox`, который имеет конструктор с параметром `int`. Однако у вас нет конструктора по умолчанию (то есть конструктора без параметров):
```cpp
NumberBox(); // Это конструктор по умолчанию
```
2. **Инициализация члена класса**: Когда вы создаете объект класса `BoxContainer`, компилятор пытается инициализировать член `nbox` (типа `NumberBox`) с помощью конструктора по умолчанию. Поскольку в вашем классе `NumberBox` конструктор без параметров не определен, компилятор не может создать объект `nbox`, и вы получаете соответствующую ошибку.
### Почему использование указателя решает проблему?
Когда вы используете указатель:
```cpp
BoxContainer(NumberBox* nb);
```
Вы можете просто хранить указатель на уже существующий объект `NumberBox`, и в этом случае конструктор `BoxContainer` не пытается создать новый объект, а просто сохраняет адрес переданного объекта. Это избавляет компилятор от необходимости вызывать конструктор по умолчанию.
### Как исправить ошибку?
Есть несколько способов исправить вашу программу:
1. **Добавить конструктор по умолчанию в класс `NumberBox`**:
```cpp
class NumberBox {
int number;
public:
NumberBox(int i);
NumberBox() : number(0) {} // Конструктор по умолчанию
int get();
};
```
2. **Использовать инициализацию через список и передать объект по константной ссылке**:
В вашем классе `BoxContainer` можно изменить объявление конструктора на:
```cpp
BoxContainer(const NumberBox& nb) : nbox(nb) {}
```
Однако для этого вам нужно будет определить как минимум оператор копирования. Если вы используете обычный тип `int`, то это будет автоматически сделано.
3. **Использовать указатель (как вы уже заметили)**:
Используйте указатель на `NumberBox`, что избавит вас от необходимости создавать объект `nbox` на стеке.
Например:
```cpp
class BoxContainer {
NumberBox* nbox; // Указатель
public:
BoxContainer(NumberBox* nb) : nbox(nb) {}
void say();
};
```
### Вывод
Ошибки, подобные вашей, происходят из-за попытки неявной инициализации объектов, для которой компилятору нужно больше информации. Используйте указатели, добавьте конструктор по умолчанию или меняйте способ передачи объектов (ссылки или указатели) в зависимости от ваших требований к дизайну программы.