2013-10-16 243 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; 
    } 
};