Член класса без конструктора по умолчанию

Предположим, у меня есть класс 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);
}
};

5

Решение

Объекты-члены всегда инициализируются перед входом в тело (часть между фигурными скобками) конструктора. Если вы не упомянули члена в списке инициализатора, он будет создан по умолчанию. Так что упомяните это!

B::B(int j) : _a(factoryA(0 < j)) { };

Это вызывает функцию factoryA со значением аргумента true если j больше 0 и false в противном случае и инициализирует член _a со значением, возвращаемым этим вызовом.

6

Другие решения

Мне не совсем понятно, почему, если бы кто-то мог мне это объяснить, было бы здорово.

Для классов [*] _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);
}
[*] Я знаю, есть исключения.

5

В этом случае лучше использовать указатель на A, то есть A * _a, а затем вызывать конструктор A где угодно.

0
По вопросам рекламы [email protected]