Конструкторы из C ++ 11 позволяют нам создавать цепочки конструкторов. Например, мы можем закодировать это:
Class Foo
{
public:
Foo()
{
}
Foo(int n): Foo()
{
}
};
Я попытался делегировать Foo () как в списке инициализации члена, так и в теле кода. Я получаю одинаковые возвращаемые значения в обеих ситуациях. У меня вопрос, есть ли на самом деле какие-либо различия в обоих методах? Если они одинаковы, есть ли преимущество перед применением одного над другим?
[Class.base.init] / 6 достаточно ясно, как делегировать конструкторы, и это не могу быть сделано в теле конструктора.
#include <iostream>
struct A
{
A() : a(42) {}
A(int) : A() {}
int a = 17;
};
struct B
{
B() : b(42) {}
B(int) { B(); }
int b = 17;
};
int main()
{
A a{0};
B b{0};
std::cout << a.a << " " << b.b << std::endl;
}
Идея очень проста: каждый из двух struct
S выставляет конструктор, принимающий один int
(это игнорируется). A
делегирует его конструктору по умолчанию в списке инициализатора члена (настройка a
до 42). B
пытается сделать то же самое в теле конструктора.
Этот пример компилируется[Godbolt], и вызывает правильные конструкторы (A(int)
а также B(int)
), но результат очень отличается
$ ./a.out
42 17
B
конструктор по умолчанию был никогда не звонил
Какие B(int)
действительно не делегирует конструктор. Вместо этого это создает новый временный объект типа B
(так же, как вы могли бы сделать B b = B();
) и сразу же отбрасывает его. Это не делегирует ничего в любом случае.
Единственный способ делегировать конструктор — вызвать его в списке инициализатора члена. Вы также можете делегировать только одному конструктору за раз.[Это не относится к конструкторам базовых классов, вызываемых очень похожим образом]
Других решений пока нет …