Classes and class hierarchies
C.41
Конструктор должен создавать полностью инициализированный объект
Причина
Конструктор устанавливает инвариант для класса. Пользователь класса должен быть в состоянии предположить, что построенный объект можно использовать.
Пример, плохо
class X1 {
FILE* f; // вызовите init() перед любой другой функцией
// ...
public:
X1() {}
void init(); // инициализировать f
void read(); // читать из f
// ...
};
void f()
{
X1 file;
file.read(); // сбой или плохое чтение!
// ...
file.init(); // слишком поздно
// ...
}
Компиляторы не читают комментарии.
Исключение
Если удобный объект нельзя построить конструктором, используйте функцию фабрики.
Применение
- (Простое) Каждый конструктор должен инициализировать каждый член данных (либо явно, через вызов делегирующего конструктора, либо через построение по умолчанию).
- (Неизвестно) Если конструктор имеет контракт
Ensures, попытайтесь проверить, выполняется ли он как постусловие.
Примечание
Если конструктор получает ресурс (для создания действительного объекта), этот ресурс должен быть освобожден деструктором. Идиома наличия конструкторов, получающих ресурсы, и деструкторов, освобождающих их, называется RAII ("Resource Acquisition Is Initialization").