我在派生类中有一个类内初始化的const成员,我想将其传递给基类的构造函数。
示例:
class Base{
public:
Base(int a) : i(a){}
private:
int i;
};
class Derived : Base{
public:
Derived() : Base(a){}
private:
const int a = 7;
};
int main(){
Derived d;
}
然而,这会产生一个未初始化的错误:
field 'a' is uninitialized when used here [-Wuninitialized]
我的印象是const初始化它会直接设置值,允许它以这种方式从派生的ctor传递。我做错了什么还是我的印象不对? const类内初始化成员何时初始化?
答案 0 :(得分:5)
在创建对象期间初始化基类和类成员时,初始化顺序为:
所以Base(a)
发生在a = 7
之前。
解决此问题的一种方法是将a
设为static const
或static constexpr
。无论如何,这可能是一个好主意,因为非静态const
变量使您的类更难以使用。 (例如,不会有隐式生成的拷贝构造函数)。
答案 1 :(得分:4)
你的问题,
const in-class初始化成员何时初始化?
有点红鲱鱼。 "课堂初始化"并不意味着什么; 大括号或相等的初始化程序基本上只是语法糖,取代了相应的构造函数initalizer list slot。 const
也没有特别的影响。所以真正的问题应该是:
何时初始化非静态数据成员?
细节实际上并不重要,只需说明在基础子对象初始化后初始化非静态数据成员,因此您提出的构造无法正常工作。
直截了当的答案是不使用 brace-or-equals-initializer 并只使用普通(可能是默认的)构造函数参数。以下是一些例子:
struct Foo : Base
{
const int a;
// Default constructor, mention value only once
Foo(int _a = 10) : Base(_a), a(_a) {}
// DRYolent default constructor
Foo() : Base(10), a(10) {}
// Delegating default constructor
Foo() : Foo(10) {}
private: Foo(int _a) : Base(_a), a(_a) {}
};
或者,如果常量的值不需要是可配置的,那么你可以使它成为每类常量(而不是每个对象):
struct Foo : Base
{
static const int a = 10;
Foo() : Base(a) {}
};
const int Foo::a; // only if you ODR-use Foo::a