2011-06-10 69 views
4

我一直在摆弄一个程序大约20分钟,我发现由于某种原因它不会让我在初始化列表中使用继承变量。这个程序,例如:使用初始化器列表和继承变量

class A { 
protected: 
     int i; 
}; 

class B : public A { 
public: 
     B() : i(45) { } 
}; 

int main() { 
     B b; 
} 

会给出错误

error: class ‘B’ does not have any field named ‘i’

但是,如果你改变了构造这样:

B() { i = 45; } 

它编译。

我从来不知道你不能初始化继承变量。我的问题是,为什么?

回答

10

一个对象只能初始化一次:当它初次出现时。

A初始化其构造函数的所有成员变量(在构造函数的主体执行之前)。因此,B无法初始化成员变量A,因为成员变量已由构造函数A初始化。

(在这种特定的情况下,技术上i是因为A没有初始化未初始化;这么说,它仍然是A的责任来初始化它的成员变量。)

+0

好吧,*严格来说*,全局变量可以初始化两次。首先是零初始化,然后是初始化它。仍然,这个案件正确。 :) – Xeo 2011-06-10 23:06:41

+0

啊,这是非常有道理的。谢谢。 – 2011-06-10 23:07:21

2

您必须定义与参数公共构造在类A中。然后在类B中使用基类的构造函数。 示例:

#include <iostream> 
using namespace std; 

class A { 
protected: 
    int i; 
public: 
    A(int number) : i(number) {} 
}; 

class B : public A { 
public: 
    B() : A(45) { } 
}; 

int main() { 
    B b; 
} 
4

您不能在C++中执行此操作。正常的方法是在父类中有一个(protected)构造函数,该构造函数接受用于设置变量的参数。

使用像这样的受保护的属性几乎从来不会被建议,因为它允许子类违反父类不变量,这只会导致严重的调试头痛。