我想初始化类中的一堆成员以保持源文件更干净。但是,这些对象采用我仅通过构造函数接收的参数,并且可以在构造函数初始化列表中或通过赋值在构造函数中初始化。(第二个选项肯定行不通。这基本上是这样的场景:
在页眉中
class Foo
{
public:
Foo(Pointer * ptr);
private:
Pointer * ptr;
Member m1{ptr, "SomeText"};
Member m2{ptr, "SomeOtherText"};
}
在CPP中
Foo::Foo(Pointer*ptr) :
ptr(ptr)
{
// ...
}
现在的问题是:标准是否说明了ptr
和m1
/m2
之间的初始化顺序?显然,只有在m1
和m2
之前初始化ptr
时,此代码才有效。
这是由标准保证的,即非静态数据成员将按照其在类定义中的声明顺序进行初始化。它们的初始化方式(通过默认成员初始值设定项或成员初始值设定项列表(以及这些初始值设定项的顺序无关紧要。
[class.base.init]#13.3
(13.3( - 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样,无论 mem 初始值设定项的顺序如何(。
[ 注意:声明顺序是为了确保基对象和成员子对象以与初始化相反的顺序销毁。
这意味着,初始化顺序将始终ptr
->m1
->m2
。
类定义中的顺序很重要,它决定了初始化的顺序。除了重新定义你的类(即交换顺序(之外,没有办法摆脱这个顺序。
进入构造函数主体后,可以将任何非 const 成员变量的值与所需的任何值一起分配,但这一点上,它们已经被初始化了。如果你想在此之前初始化一个成员,你必须在构造函数体之前完成 - 即使用Foo::Foo(Pointer * ptr) : ptr(ptr) {}
或通过初始化它们来初始化它们,就像你对m1
和m2
所做的那样。
它是标准定义的。成员按类内的声明顺序初始化,因此您的代码完全有效。潜在的危险是构造函数中的初始化顺序与成员顺序不一致 - 然后仍然以声明顺序启动字段。