Ссылка на неинициализированный объект 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 для этого потребуется указатель (поскольку ссылки не могут быть переназначены другому объекту)

Другие вопросы по тегам