2009-10-17 160 views
1

是否有類似於此的可能?這樣它會產生一個錯誤。虛擬非方法成員

class A { 
    public: 
    virtual std::string key; 
}; 

class B : public A { 
    public: 
    std::string key; 
}; 

int main() 
{ 
    A a; 
    a.key = "Foo"; 
    return 1; 
} 
+0

目前還不清楚你正在尋找什麼樣的行爲。如果您在main()函數中添加更多代碼來解釋您要查找的行爲,這將有所幫助。 不,它使虛擬數據成員沒有意義。 – zumalifeguard 2009-10-17 05:47:06

回答

8

不,因爲這沒有意義。請記住,一個子類包含其父類的所有成員;因此,B仍然有Astd::string key。此外,由於Bstd::string key是同一類型,它是絕對相同的A的 - 所以重寫它的意義是什麼?

另外,請注意,在施工期間,當我們運行A的構造函數時,B的虛擬方法將不會被調用。這意味着如果我們在A的建設期間訪問key,我們會得到A的密鑰 - 但是當B被構建時,那個key會被遮蔽,其數據完全無法訪問。

也就是說,如果你真的想要做這樣的事情,出於某種原因,你需要使用虛擬存取函數:

class A { 
    private: 
    std::string m_key; 
    public: 
    virtual std::string &key() { return m_key; } 
    virtual const std::string &key() const { return m_key; } 
}; 

class B : public A { 
    private: 
    std::string m_key; 
    public: 
    virtual std::string &key() { return m_key; } 
    virtual const std::string &key() const { return m_key; } 
}; 

int main() 
{ 
    B b; 
    b.key() = "Foo"; 
    return 0; 
} 
0

類方法的代碼。代碼是不變的。每個特定的類方法都有一個在編譯時定義的預定的固定行爲,在運行時無法更改。出於這個原因,爲了擁有多態類,我們必須事先(即在編譯時)編寫不同版本的不同方法,然後在運行時將這些版本的特定集合「附加」到類實例中,從而形成每個實例的特定運行時行爲。

與數據成員的情況是完全不同的。數據成員不固定。他們是多變的。它們保存值,這些值可以在運行時自由更改。僅憑這一點,數據成員本身就是「虛擬」的。您不需要在派生類中引入不同的「版本」數據成員。相反,您只需將不同的值放入已存在的數據成員中即可。這一點已經類似於類方法的「虛擬性」。而且,這種「數據虛擬性」比方法的「虛擬性」更加靈活,因爲對於數據成員,您不限於預先確定的一組值。

你的建議雖然看起來像一個更高程度的「虛擬性」:不僅數據成員的值是可變的,而且數據成員本身是可覆蓋的。 (稱之爲元虛擬或超虛擬或雙虛擬。)但是,具有這種特性的重點,好處和用途是什麼?我個人不會馬上看到它,而你的代碼示例並不完全可以說明。