Проблемы с порядком инициализации
Учитывая пример кода:
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, или это инициализируется по умолчанию, так как это тип класса внутри класса?
Нет, все в порядке.