成员变量是否可用于初始化列表中的其他成员
Can member variables be used to initialize other members in an initialization list?
考虑以下(简化的)情况:
class Foo
{
private:
int evenA;
int evenB;
int evenSum;
public:
Foo(int a, int b) : evenA(a-(a%2)), evenB(b-(b%2)), evenSum(evenA+evenB)
{
}
};
当我像这样实例化 Foo 时:
Foo foo(1,3);
那么偶数A是0,偶数B是2,但是偶数总和会初始化为2吗?
我在当前的平台 (iOS) 上尝试了这个,它似乎有效,但我不确定这段代码是否可移植。
感谢您的帮助!
这是定义明确且可移植的,1 但它可能容易出错。
成员按照它们在类主体中声明的顺序进行初始化,而不是按照它们在初始化列表中列出的顺序进行初始化。 因此,如果更改类主体,此代码可能会静默失败(尽管许多编译器会发现这一点并发出警告)。
1. 从 C++ 标准中的 [class.base.init] :
在非委托构造函数中,初始化按以下顺序进行:
- 首先,并且仅对于派生最多的类 (1.8) 的构造函数,虚拟基类初始化在 它们出现在基类有向无环图的深度优先从左到右遍历上的顺序, 其中"从左到右"是基类在派生类基说明符列表中的出现顺序。
- 然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化 (无论 mem 初始值设定项的顺序如何)。
- 然后,按照非静态数据成员在类定义中声明的顺序初始化它们 (同样,无论 mem 初始值设定项的顺序如何)。
- 最后,执行构造函数主体的复合语句。
(突出显示是我的。
然后,标准的这一部分继续给出使用成员变量初始化其他成员变量的示例。
是的,前提是它们已经被构建好了。 只是不要忘记构造顺序是声明中的顺序类定义,而不是初始值设定项在构造 函数。 而且编译器通常不会告诉你是否使用一个变量,在构造之前。 例如,在您的情况下,如果evenSum
移动到类的顶部,则未定义行为(因为它的初始值设定项使用未初始化的成员),甚至尽管在构造函数中,您可以初始化evenA
并以词法evenB
在evenSum
之前.
成员
按照它们在类定义中声明的顺序进行初始化。只要初始值设定项列表遵循此顺序,它就应该没问题。
调用初始值设定项的顺序:初始化顺序
列表中成员初始值设定项的顺序无关紧要:初始化的实际顺序如下:
- 如果构造函数用于派生最多的类,则虚基将按照它们在基类声明的深度优先从左到右遍历中出现的顺序进行初始化(从左到右是指基说明符列表中的外观)
- 然后,直接碱基按从左到右的顺序初始化,因为它们出现在此类的基本说明符列表中
- 然后,非静态数据成员按照类定义中的声明顺序进行初始化。
- 最后,执行构造函数的主体
所以是的,你的示例将起作用,只要在evenSum
之前声明evenA
和evenB
这也在 g++ 4.0.3(现在已经 6 岁了)上编译没有错误。
我相信这将在任何合理的最新编译器上编译良好。
相关文章:
- 保留对其他类的成员函数的引用
- 成员包含其他继承类的继承类?
- 线程消息传递或更好:在"大师班"中访问其他班级的成员
- 锁定来自其他线程的类成员
- 为什么我可以访问其他班级的私人成员?
- C++:从其他类访问结构的私有成员向量
- 将基类的成员函数重载到其他派生类C++
- 用于对项目进行分组并将单个项目映射到其他组成员的数据结构
- 只对向量中的一个类成员进行排序,其他成员保持不变
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- 使用其他成员初始化结构的成员?
- 其他类的成员函数对成员函数的嵌套引用
- C++ 将类成员函数传递给其他类
- 访问其他类中多个对象的私有成员向量
- 对 Eclipse 项目库的更改将还原给团队的其他成员
- 其他成员函数的通用"成员函数"包装器?
- 在另一个 QThread 上运行成员方法时,无法将事件发送到其他线程拥有的对象
- 如果类包含基类类型的成员作为第一个元素,后跟其他成员,编译器是否可以优化空基?
- 将成员函数作为参数传递给其他成员函数 (C++ 11 <function>)
- 将元组成员包装在其他模板化类型中