2011-06-10 67 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)構造函數,該構造函數接受用於設置變量的參數。

使用像這樣的受保護的屬性幾乎從來不會被建議,因爲它允許子類違反父類不變量,這隻會導致嚴重的調試頭痛。