[英]Why can't Initialize the data member of base class in the constructor initializer list of derived class?
such is the code,and with the error:"illegal member initialization: 'a' is not a base or member",what is the meaning of the error info,and why?? 这就是代码,并带有错误:“非法成员初始化:'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
}
By the time the constructor of the derived class is invoked, the base class must already be constructed. 在调用派生类的构造函数时,必须已经构造了基类。 So it's already too late.
所以现在已经太晚了。 To see why it must be this way, consider:
要了解为什么必须这样,请考虑:
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) { ; }
}
Now, think about it. 现在,想一想。 The
Middle
constructor has to run before the Derived
constructor. Middle
构造函数必须在Derived
构造函数之前运行。 And the Middle
constructor ensures that i
is 2. So how can the Derived
constructor later re-construct it with a different value? 而
Middle
构造函数确保i
是2.那么Derived
构造函数如何能够在以后使用不同的值重新构造它?
See this answer for a more complete explanation of what's going on here. 请参阅此答案 ,以获得有关此处发生的更完整的解释。 Basically, you cannot initialise
A::a
in the initialiser of B
, because it is ill-formed according to the standard. 基本上,你不能在
B
的初始化中初始化A::a
,因为它根据标准是不正确的。
Because the base class may want to initialize things its own way. 因为基类可能希望以自己的方式初始化事物。 The proper method is to call on of the base constructors in the initializer list and let the base ctor initialize itself.
正确的方法是调用初始化列表中的基础构造函数,并让base ctor初始化自己。
One more important piece of information - remember that if a class does not initialise a member object via the constructor initialization list, then the default constructor for that member will be invoked before that first statement in the base class constructor is executed. 一个更重要的信息 - 记住,如果类没有通过构造函数初始化列表初始化成员对象,那么在执行基类构造函数中的第一个语句之前,将调用该成员的默认构造函数。 When you use the initialiser, what you are actually doing is specifying a constructor to be used INSTEAD of the default constructor.
当您使用初始化器时,您实际执行的是指定要使用默认构造函数的INSTEAD的构造函数。
Clearly when you are constructing a derived class, the parent class member has thus already been constructed, so you cannot reconstruct the base member again, which is what you are trying to do in this example by including it in the derived class initialisation list. 显然,当您构造派生类时,父类成员已经被构造,因此您无法再次重构基本成员,这是您在此示例中尝试通过将其包含在派生类初始化列表中而执行的操作。
As an aside, if you all you want is to have the derived class be able to set the value of A::a to a specific value, then use the following code instead: 顺便说一句 ,如果你想要的是派生类能够将A :: a的值设置为特定值,那么请使用以下代码:
B::B()
{
a = 10;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.