【问题标题】:Why can't Initialize the data member of base class in the constructor initializer list of derived class?为什么不能在派生类的构造函数初始化列表中初始化基类的数据成员?
【发布时间】:2012-08-07 02:28:14
【问题描述】:

代码就是这样,并且出现错误:“非法成员初始化:'a'不是基础或成员”,错误信息的含义是什么,为什么??

class A{
public:
int a;
};
class B:public A{

public:
B();
};

B::B():a(10){    // put  "a(10)" into the constructor body is right

}

【问题讨论】:

标签: c++ inheritance constructor initializer-list


【解决方案1】:

在调用派生类的构造函数时,必须已经构造了基类。所以已经太晚了。要了解为什么必须这样,请考虑:

class Base
{
    public:
    int i;
    Base(int q) : i(q) { ; }
};

class Middle : public Base
{
    public:
    Middle() : Base(2) { printf("i=%d\n", i); }
};

class Derived : public Middle
{
    public:
    Derived() : i(3) { ; }
}

现在,考虑一下。 Middle 构造函数必须在 Derived 构造函数之前运行。而Middle 构造函数确保i 为2。那么Derived 构造函数以后如何用不同的值重新构造它呢?

【讨论】:

    【解决方案2】:

    请参阅this answer 以更完整地了解此处发生的情况。基本上,你不能在B的初始化器中初始化A::a,因为按照标准它是不正确的。

    【讨论】:

      【解决方案3】:

      还有一条更重要的信息——请记住,如果一个类没有通过构造函数初始化列表来初始化一个成员对象,那么该成员的默认构造函数将在基类构造函数中的第一条语句执行之前被调用。当你使用初始化器时,你实际上是在指定一个构造函数来代替默认构造函数。

      很明显,当您构造派生类时,父类成员已经被构造,因此您不能再次重构基成员,这就是您在本示例中尝试通过将其包含在派生类初始化中所做的事情列表。

      顺便说一句,如果您只想让派生类能够将 A::a 的值设置为特定值,请改用以下代码:

      B::B()
      {
          a = 10;
      }
      

      【讨论】:

        【解决方案4】:

        因为基类可能希望以自己的方式初始化事物。正确的方法是调用初始化列表中的基础构造函数,让基础 ctor 自行初始化。

        【讨论】:

          猜你喜欢
          • 2023-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多