Ссылка на неинициализированный объект iniside constructor
Можно передать неинициализированный объект в родительский класс, как в следующем примере
class C
{
public:
C(int i):
m_i(i)
{};
int m_i;
}
class T
{
public:
T(C & c):
m_c(c)
{
};
C & m_c;
};
class ST : public T
{
public:
ST():
T(m_ci),
m_ci(999)
{
};
C m_ci;
};
В class T
конструктор, c
ссылка на неинициализированный объект Если class T
использовали c
объект во время строительства, это может привести к ошибке. Но так как это не так, это компилируется и работает нормально. Мой вопрос - это тормозит какую-то парадигму или хорошие директивы дизайна? Если так, каковы альтернативы, потому что я нашел полезным выделить объект, требуемый родителем в подклассе.
Кстати, мне интересно, почему невозможно изменить порядок инициализации, чтобы конструктор базового класса вызывался после инициализации некоторых членов.
3 ответа
Вы можете, но вы получите неопределенное поведение.
В утилитах Boost вы найдете идиому " база от члена", созданную R Samuel Klatchko. По сути, вы делаете личную базу вместо частного члена. Эта база инициализируется первой, и вы можете использовать ее для других баз:
// ...
class C_base
{
public:
C_base(int i) :
m_ci(i)
{}
C m_ci;
};
class ST :
private C_base
public T
{
public:
ST() :
C_base(999),
T(m_ci),
{
};
};
Утилита Boost устраняет повторный код.
Передача ссылки или указателя на что-то неинициализированное технически совершенно нормально.
Но причина, по которой вы спрашиваете, возможно, заключается в том, что вы думаете, что что-то легко может пойти не так, что через некоторую цепочку вызовов можно случайно получить доступ к объекту до его инициализации. И я думаю, что это серьезная проблема. И есть еще одна вещь, которая может пойти не так, а именно этот код в базовом классе T
может теперь сделать недействительным инвариант класса ST
путем непосредственного изменения члена данных ST
пример...
Так что я думаю, что это немного рискованно.
Что касается порядка инициализации, C++ основан на идее построения из частей вверх, в иерархии. Если конструктор выбрасывает, то полностью сконструированные вещи уничтожаются автоматически. Это было бы более сложно или менее эффективно при более произвольном порядке построения.
Ура & hth.,
Я видел это много, и многие компиляторы будут предупреждать. Это нормально, если T
конструктор никогда не разыменовывает c
ссылка.
Если вы не хотите предупреждение, вам нужно сделать два этапа строительства. Сделать защищенный Init(C&)
метод в T
, а затем позвоните в ST
тело конструктора - к сожалению m_c
для этого потребуется указатель (поскольку ссылки не могут быть переназначены другому объекту)