class D: A
{
B obj;
C obj2;
}
这里的构造顺序保证?
我知道D将在A,B和C之后构建,但我真正想知道的是A是否保证在B或C之前构建,或者甚至B是否< em>保证在C之前构建。
我知道你可以有一个明确的初始化列表:
D(): A(), B(), C()
{}
但是初始化列表是否确定了初始化的顺序?
此外,是否有任何组件是否具有默认构造函数?
答案 0 :(得分:10)
来自C ++ 03标准ISO / IEC 14882:2003(E)§12.6.2/ 5 [class.base.init]:
初始化应按以下顺序进行:
- 首先,仅对于如下所述的派生类最多的构造函数,虚拟基类应按它们出现在基类有向无环图的深度优先从左到右遍历的顺序进行初始化,其中“ “从左到右”是派生类 base-specifier-list 中基类名称的出现顺序。
- 然后,直接基类应按照它们出现在 base-specifier-list 中的声明顺序进行初始化(无论 mem-initializers 的顺序如何)。 /> - 然后,非静态数据成员应按照在类定义中声明的顺序进行初始化(同样不管 mem-initializers 的顺序如何)。
- 最后,执行构造函数的主体 [注意:声明命令是强制要求确保以初始化的相反顺序销毁基础和成员子对象。 ]
所以在这种情况下,你可以保证初始化的顺序首先是基类A
,然后是子对象B
(因为它首先出现在类的类成员列表中定义),然后是子对象C
。初始化程序列表的顺序是无关紧要的,无论是否有任何成员都有或没有默认构造函数 - 如果成员没有默认构造函数并且它没有在初始化程序列表中显式初始化,那么它具有一个未指明的值。
答案 1 :(得分:9)
但是初始化列表是否确定了初始化的顺序?
否即可。初始化列表不确定成员数据和基础子对象的初始化顺序。成员按其声明的顺序初始化,基础子对象按其提及的顺序构建 - 从左到右:
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
它们以相反的顺序被破坏。
答案 2 :(得分:1)
也许这个破解代码的例子将有助于说明:
如果我这样定义一个类:
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
的初始化将导致段错误。
也许有人可以引用标准的相应部分来指示这种行为。
对于问题的后半部分,基类将始终在类拥有成员之前初始化。