2013-10-16 266 views
2

据我所知,当我在派生类初始化列表中初始化基类时,立即构造基类,然后基类元素可用。如果这是正确的,为什么这不起作用?使用构造函数初始化列表来初始化基类的元素

class Base 
{ 
public: 
    int elem; 
} 

class Derived : public Base 
{ 
    Derived() : Base(), elem(1) {} 
    // error: class 'Derived' does not have any field named 'elem' 
} 

注:在我来说,我不能作出Base任何改变(这是一个固定的接口类)。

+0

我在回避你的直接问题,但是 - 这是'Base'的初始化工作,IMO。 –

+0

@BrianCain在我的情况下'Base'是一个包含实现('Derived')可以定义的回调函数对象的接口。 – arman

回答

2

构造函数只能构造它自己的类的成员。你需要给Base一个合适的构造函数:

class Base 
{ 
public: 
    Base() : elem(23) { } 
    int elem; 
protected: 
    Base(int n) : elem(n) { } 
}; 

class Derived : public Base 
{ 
    Derived() : Base(1) {} 
}; 
+0

如果'Base'不能改变,你能不能提供最佳实践方法? – arman

+0

@ausairman:不要使用'Base' :-)你总是可以使用赋值,但它不是“最佳实践”。 –

0

ELEM属于Base类,所以基地负责初始化它。

正确的代码如下所示:

class Base 
{ 
public: 
    int elem; 
    Base(int n) : elem(n) {} 
}; 

class Derived : public Base 
{ 
    Derived() : Base(1) {} 
}; 
0

只能在初始化列表中未基类成员初始化类和基类的成员。

如果您想重写基类成员的值,请在构造函数的主体中执行此操作。

2

初始化程序列表用于初始化该类的直接成员和基础子对象,而不是基类的成员。基类成员由基类构造函数初始化,并且不能初始化任何东西两次。

如果你要重新分配的基类成员后,它被初始化,那么您可以:

Derived() : Base() {elem = 1;} 

,或者你可以允许该值通过传递给基类的构造函数:

explicit Base(int e) : elem(e) {} 
Derived() : Base(1) {} 

虽然您添加到问题的注释表明这不是您的特定情况下的选项。

0

在这种情况下,您不能在初始化程序列表中初始化elem,而必须在函数体中初始化它。

class Base { 
public: 
    int elem; 
}; 

class Derived : public Base { 
public: 
    Derived() : Base() { 
    elem = 1; 
    } 
};