Предположим, у меня есть класс A без конструктора по умолчанию, фабричный метод factoryA, который
возвращает объект типа A и класс B, в котором A является его членом. Я знаю, что в этом случае член типа A из B должен быть инициализирован в списке инициализации конструктора B. Мне не совсем понятно, почему, если бы кто-то мог мне это объяснить, было бы здорово. Кроме того, что, если параметр для конструктора A должен быть вычислен внутри конструктора B, скажем, путем запроса базы данных или чего-то в этом роде? Есть ли способ использовать настройки ниже, не предоставляя A конструктором по умолчанию? Заранее спасибо.
class A {
private:
int _i;
public:
A(int i) : _i(i) {}
};
A factoryA(bool b) {
if(b)
return A(1);
else return A(2);
}
class B {
private:
A _a;
public:
B(int j) {
if(j > 0)
_a = factoryA(true);
else _a = factoryA(false);
}
};
Объекты-члены всегда инициализируются перед входом в тело (часть между фигурными скобками) конструктора. Если вы не упомянули члена в списке инициализатора, он будет создан по умолчанию. Так что упомяните это!
B::B(int j) : _a(factoryA(0 < j)) { };
Это вызывает функцию factoryA
со значением аргумента true
если j
больше 0 и false
в противном случае и инициализирует член _a
со значением, возвращаемым этим вызовом.
Мне не совсем понятно, почему, если бы кто-то мог мне это объяснить, было бы здорово.
Для классов [*] _a = factoryA(true);
вызовы по линии _a.operator=(factoryA(true))
, Вызов функции-члена на _a
требует _a
уже быть инициализированным. Так что, если бы это не была ошибка во время компиляции, она все равно не была бы действительной.
Кроме того, что, если параметр для конструктора A должен быть вычислен внутри конструктора B, скажем, путем запроса базы данных или чего-то в этом роде? Есть ли способ использовать настройки ниже, не предоставляя A конструктором по умолчанию?
Пока A
имеет конструктор копирования или перемещения, вы можете инициализировать его возвращаемым значением функции, и эта функция может делать все что угодно, даже используя различные конструкторы для A
в зависимости от предоставленных аргументов.
class B {
private:
A _a;
static A getA(int i);
public:
B(int j) : _a(getA(j)) {
}
};
A B::getA(int j)
{
if (j > 0)
return factoryA(true);
else
return factoryA(false);
}
[*] Я знаю, есть исключения.
В этом случае лучше использовать указатель на A, то есть A * _a, а затем вызывать конструктор A где угодно.