Jest to oczekiwane zachowanie, ponieważ inicjalizacja członka odbywa się przed treścią konstruktora. Dla realizacji tego warto dodać inicjatorów członka, jak również:
template<typename T>
struct B
{
A a;
T b;
B()
:
a(),
b()
{
std::cout<<"B()"<<std::endl;
}
};
Aby w pełni zrozumieć kolejność wykonywania, dodajmy obojętne pole całkowitą. Dodałem również szablon do wyświetlenia zagnieżdżenia. Zobacz wersję demonstracyjną: http://ideone.com/KylQQb.
#include <cstdio>
struct A
{
A()
:
dummy(printf("Starting to construct A()\n"))
{
printf("Fully constructed A()\n");
}
int dummy;
};
template <typename T>
struct Nesting;
template <>
struct Nesting<int>
{
constexpr static int value = 0;
};
template <template <typename> class T, typename I>
struct Nesting<T<I>>
{
constexpr static int value = 1 + Nesting<I>::value;
};
template<typename T>
struct B
{
int dummy;
A a;
T b;
B()
:
dummy(printf("Starting to construct B() with nesting %d\n", Nesting<B<T>>::value)),
a(),
b()
{
printf("Fully constructed B() with nesting %d\n", Nesting<B<T>>::value);
}
};
int main()
{
B<B<B<int>>> Test;
return 0;
}
Wyjście to będzie
Starting to construct B() with nesting 3
Starting to construct A()
Fully constructed A()
Starting to construct B() with nesting 2
Starting to construct A()
Fully constructed A()
Starting to construct B() with nesting 1
Starting to construct A()
Fully constructed A()
Fully constructed B() with nesting 1
Fully constructed B() with nesting 2
Fully constructed B() with nesting 3
Zmienne użytkownika są inicjowane zanim skończy ciało konstruktora. – immibis