将类初始化的const成员传递给Base构造函数?

时间:2015-04-09 22:46:29

标签: c++ c++11

我在派生类中有一个类内初始化的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类内初始化成员何时初始化?

2 个答案:

答案 0 :(得分:5)

在创建对象期间初始化基类和类成员时,初始化顺序为:

  • 虚拟基类,按树顺序
  • 直接非虚拟基类,按顺序
  • 非静态数据成员,按其声明顺序。

所以Base(a)发生在a = 7之前。

解决此问题的一种方法是将a设为static conststatic 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