Проблемы с порядком инициализации

Учитывая пример кода:

class B {
    //Some contents.
};

class C {
    private:
        B& b;
};

class A {
    private:
        B b;
        C c;
};

Класс C имеет ссылку на a b, поэтому его необходимо инициализировать. Класс A содержит экземпляр B и экземпляр C.

Мой вопрос: могу ли я инициализировать экземпляр C в A с экземпляром B в A (при условии, что я потрудился поместить конструкторы)? Во-вторых, мне нужно выполнить какую-либо явную инициализацию B в A, или это инициализируется по умолчанию, так как это тип класса внутри класса?

4 ответа

Решение

Переменные-члены инициализируются в том порядке, в котором они были объявлены в объявлении класса (даже если они есть в другом порядке в списке инициализации конструктора), поэтому да, к тому времени c инициализируется, b будет инициализирован, и вы можете использовать b инициализировать c,

Как отмечает Рикардо Карденес, он все равно будет работать, даже если вы объявите c до b в определении класса (что означает, что вы пройдете C::C ссылка на неинициализированный B) однако вы вызываете неопределенное поведение, если используете объект внутри C::C, Безопаснее объявить b во-первых, потому что, хотя вы не можете использовать b внутри C::C Теперь вы можете в будущем забыть, что ссылка относится к неинициализированному Bи вызвать UB.

И нет, вам не нужно явно инициализировать b (если это не POD), если вы не хотите, чтобы он был построен по умолчанию. Так что этот код будет тем, что вы хотите (опять же, если B не POD):

A::A() : c(b) { }

На ваш первый вопрос: вы можете инициализировать его, написав конструкторы так:

C::C(B& bInst): b(bInst){}
A::A():b(), c(b) {}

Конечно, если ваш конструктор C на самом деле использует b (а не только его адрес), вам нужно убедиться, что порядок инициализации остается прежним, поэтому b должен быть объявлен до c, поскольку члены инициализируются в том порядке, в котором они объявлены (даже если в списке initializaiton они расположены в другом порядке).

И нет, вам не нужно явно инициализировать B, поскольку он будет создан по умолчанию, если вы этого не сделаете. Конечно, если B является POD, это означает, что он остается неинициализированным (при явной инициализации с использованием b() в списке инициализатора A() будет инициализировать его 0).

Да, поскольку C содержит только ссылку на B, а не отдельный экземпляр, вы можете поместить конструктор в C и позволить ACb ссылаться на AB

B и C внутри A оба создаются / создаются автоматически при создании экземпляра A.

Могу ли я инициализировать экземпляр C в A с экземпляром B в A (при условии, что я потрудился поместить конструкторы в)

Конечно.

Во-вторых, мне нужно выполнить какую-либо явную инициализацию B в A, или это инициализируется по умолчанию, так как это тип класса внутри класса?

Нет, все в порядке.

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