class D: A
{
B obj;
C obj2;
}
这里的结构顺序是什么保证?类别组件的初始化顺序
我知道d将A,B和C之后建造的,但我真正想知道的是A是否是保证 B或C之前建造,B甚至是保证是
D(): A(), B(), C()
{}
但这是否初始化器列表确定顺序初始化的:C.
我知道你可以有一个明确的初始化器列表以前建造的?
另外,无论是否有任何组件有或没有默认的构造函数?
class D: A
{
B obj;
C obj2;
}
这里的结构顺序是什么保证?类别组件的初始化顺序
我知道d将A,B和C之后建造的,但我真正想知道的是A是否是保证 B或C之前建造,B甚至是保证是
D(): A(), B(), C()
{}
但这是否初始化器列表确定顺序初始化的:C.
我知道你可以有一个明确的初始化器列表以前建造的?
另外,无论是否有任何组件有或没有默认的构造函数?
从C++ 03标准ISO/IEC 14882:2003(E)§12.6.2/ 5 [class.base。INIT]:
初始化按照下列顺序进行:
- 首先,只对最派生类的构造如下所述,虚拟基类,应在它们出现在一个深度的顺序进行初始化基类,其中“左到右”的向无环图的左侧-first到右遍历是在派生类碱说明符列表基类名称的显示顺序。
- 然后,直接基类应按声明顺序进行初始化,因为它们出现在基指定程序列表(不管成分初始化程序的顺序如何)中。
- 然后,非静态数据成员应在他们的类定义中声明(再次不管MEM-初始化的顺序)的顺序进行初始化。
- 最后,构造函数的主体被执行。
[注:声明顺序的任务是确保基部和构件子对象在初始化时相反的顺序被破坏。 ]
因此,在这种情况下,这样保证了初始化的顺序将是第一个基类A
,那么子对象B
(因为它第一次出现在类定义类成员的列表),然后子对象C
。初始化列表的顺序是无关紧要的,因为是是否有任何成员或不具有默认的构造函数,如果一个成员没有一个默认的构造函数,它没有明确的初始化列表初始化,那么它有一个未指定的值。
但是,初始化程序列表确定初始化的顺序吗?
否。初始化列表不确定确定成员数据和基础子对象的初始化顺序。成员在其声明的顺序初始化,并且基础子对象构建在其提及的顺序 - 从左至右:
struct A : B, C {} //B is constructed before C
此外,基子对象的成员数据的初始化之前建造。在上述结构初始化
struct A : B, C
{
D d;
E e;
};
订单:
B => C => d => e
subobject subobject member member
他们正以相反的顺序破坏。
也许断码这个例子将帮助说明:
如果我定义一个类,像这样:
class Connection {
boost::asio::tcp::ip::socket _socket;
boost::asio::io_service _io_service;
Connection() : _io_service(), _socket(_io_service)
{
}
};
这将在所有现代编译失败。由于_socket
首先被定义为类成员,但初始化列表将尝试首先初始化它,尽管初始化列表要求编译器首先初始化_io_service
。但由于_io_service
尚未初始化(套接字构造函数依赖于初始化的_io_service
),所以_socket
的初始化将导致段错误。
也许有人可以引用标准中规定这种行为的适当部分。
对于问题的后半部分,基类将始终在类自己的成员之前初始化。
你是什么意思“现代编译器”?由于至少TC3.0,我正在使用C++,并且我不记得一个编译器的初始化顺序错误。 – sbi
不要喊我! –