2010-10-21 108 views
18

我有一个关于继承成员在派生类的构造函数中初始化的问题。示例代码:C++:继承域的初始化

class A 
    { 
public: 
    int m_int; 
    }; 

class B: public A 
    { 
public: 
    B():m_int(0){} 
    }; 

此代码给我下面的输出:

In constructor 'B::B()': Line 10: error: class 'B' does not have any field named 'm_int'

(见http://codepad.org/tn1weFFP

我猜为什么出现这种情况? m_int应该是B的成员,并且在B发生时由于父构造函数在继承类的成员初始化之前运行而初始化m_int时,父类A应该已经初始化。我的推理在哪里出错?这段代码真的发生了什么?我知道其他可能性来初始化这个成员(派生构造函数的基础构造函数或赋值),但我想明白为什么它在我尝试它的方式是非法的?一些特定的C++语言功能或类似?如果可能的话,请用C++标准指出一个段落。

回答

18

您需要为A(它可被保护,只有B能调用它),它初始化m_int构造就像你有,那么你调用:A(0),你必须:m_int(0)

你也可以只设置m_int = 0在B的构造函数中。它是可访问的(正如你所描述的)它只是在特殊的构造函数语法中不可用。

+5

这是一个很好的答案,但我只是想补充一些解释。当你使用:操作符时,你告诉编译器,在它做任何事情之前,它应该运行这些指令。基本上你是在父构造函数(或其他任何东西)运行之前设置一个变量。因此该变量不存在。 :A(),m_int(0)也应该起作用。默认情况下,如果您不使用:,编译器将运行基类构造函数。换句话说,如果你什么都不做,C++会为你做默认事情,如果你开始指定事情,它会假设你知道你在做什么。 – 2010-10-21 09:29:35

+0

嗯...据我所知,父类的构造函数总是在任何其他初始化之前运行,所以当我尝试初始化时,变量m_int已经存在。所以这不应该成为问题... – Haspemulator 2010-10-21 10:30:25

+0

@Haspemulator是的,它已经存在,但这就是为什么你会得到错误。它已经由A的构造函数默认初始化了。你不能在B的构造函数中重新初始化一个变量。你可以像Ben Jackson在上面所述的那样重新分配('m_int = 0'),那就是关于它的。 – wheaties 2010-10-21 13:14:07

4

你想要的是这样的:

class A{ 
public: 
    A() : m_int(0); 
    int m_int; 
}; 

使m_int在正确的位置进行初始化。

编辑:

从上面的注释,当您尝试初始化m_int变量B编译器会抱怨的原因是,它已经被通过的A构造函数初始化。也就是说,你不能重新初始化某些东西,只能重新分配。所以,你可以重新分配像上面提到的本杰克逊,或者你可以在适当的位置进行初始化。

4

为了构建类B的实例,您首先实例化类A的实例。在该实例化过程中,m_int被初始化。在初始化之后,b的构造函数被调用,所以你不能重新初始化m_int。如果这是你的目标,那么你可以实现对A一个构造函数一个int,然后调用在B的初始化列表:

class A 
{ 
public: 
    A(int x): m_int(x) {} 
    int m_int; 
}; 

class B: public A 
{ 
public: 
    B(): A(2) {} 
}; 
+0

是否有任何原因,它在初始化列表中不可用?我知道有其他可能性来初始化这个成员(基础构造函数或派生构造函数中的赋值),但是我想明白为什么它在我尝试的方式中是非法的?一些特定的C++语言功能或类似?如果可能的话,请用C++标准指出一个段落。 – Haspemulator 2010-10-21 05:44:52

+0

这是两件事情 - 派生类首先实例化它们的基类,并且按照它们声明的顺序对它们进行初始化,而不是它们在初始化列表中出现的顺序。因此,基础的成员首先被初始化,并且不能重新初始化它们。 – 2010-10-21 16:27:51

0

使一个构造在一个 和使用B():A(2) {} 保证B():m_int(0){} 其工作。