#include <iostream>
struct A
{
A(){std::cout<<"A()"<<std::endl;}
};
template<typename T>
struct B
{
A a;
T b;
B(){std::cout<<"B()"<<std::endl;}
};
int main()
{
B<B<B<int> > > Test;
return 0;
}
调用构造函数的顺序是
A()
A()
A()
B()
B()
B()
我不知道为什么会这样。我以为这将是A B A B A B.你能解释一下为什么吗?
答案 0 :(得分:2)
这实际上是直截了当的,如果它像ABABAB一样,那么如果你想从b
的构造函数访问B
就会遇到麻烦,因为你认为的顺序意味着第一个成员{ {1}}被实例化,然后a
运行,然后ctor
被初始化。实际上,每个成员首先被实例化(构造等),然后,构造函数被调用。
答案 1 :(得分:1)
这是因为必须在执行构造函数体之前初始化成员变量。请考虑以下示例:
struct A {
int value;
// Here we explicitly initialize 'value' with 5
A() : value(5) { }
};
struct B {
A a;
B()
{
// This is perfectly valid and would print 5,
// because 'a' has already been implicitly initialized
// with its default constructor.
std::cout << a.value;
}
};
如果不是这种情况,您期望a
在B
的构造函数中具有什么价值?你会遇到各种各样的问题。因此,必须在A
的正文之前隐式调用B()
的默认构造函数。
基本上,为了使其更明确,这就是正在发生的事情:
// Initialize 'a' before body of constructor
B() : a()
{
std::cout << a.value;
}
答案 2 :(得分:1)
首先,让我们分析一下你的内容:
您有一个Test
class B<B<B<int> > >
的对象,即:
class B<B<B<int> > > {
A a;
B<B<int> > b;
};
Test
的第二个字段,Test.b
属于class B<B<int> >
,即:
class B<B<int> > {
A a;
B<int> b;
};
然后您有Test.b
,Test.b.b
的第二个字段,其为class B<int>
,即:
class B<int> {
A a;
int b;
};
所以初始化的顺序是:
A()
代表Test.a
。A()
代表Test.b.a
。A()
代表Test.b.b.a
。Test.b.b.b
的类型为int
且没有构造函数。B<int>()
代表Test.b.b
。B<B<int> >()
代表Test.b
。B<B<B<int> > >()
代表Test
。不幸的是,所有三个构造函数都在输出上写了相同的东西:B()
,但它们是不同类的不同构造函数。
答案 3 :(得分:0)
这是预期的行为,因为成员初始化发生在构造函数的主体之前。为了实现这一点,添加成员初始化器也很有帮助:
template<typename T>
struct B
{
A a;
T b;
B()
:
a(),
b()
{
std::cout<<"B()"<<std::endl;
}
};
为了完全掌握执行顺序,我们添加一个虚拟整数字段。 我还添加了一个模板来显示嵌套。有关演示,请参阅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;
}
这个输出将是
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