2011-03-05 107 views
0

我面對一些設計上的問題,我想這樣寫:C++ /鑽石繼承/靜態變量

class A { ... }; 
class B : public A { static string type_; ... }; 
class C : public A { static string type_; ... }; 
class D : public B, public C { static string type_; ... }; 

我想起來了C類的定義,我不會有任何問題..但當我定義D類會發生什麼?由於D將繼承B和C,所以我可能會含糊不清。我的最終目標是在每個類B,C和D中都有一個靜態變量,它具有相同的名稱,但是具有不同的值。那可能嗎?

提前感謝 桑達

+1

你爲什麼不試試? – thkala 2011-03-05 10:58:08

+1

@thkala:嘗試一些東西可能很有用,但它只能告訴你當前實現中會發生什麼。它不能告訴你*假設*會發生什麼,或者結果未定義。 – 2011-03-05 11:12:01

回答

3

你這裏的代碼是完全正常的。允許類使用任何名稱定義成員,即使它們與父類中成員的名稱相匹配。你唯一會遇到麻煩的是如果使用其中一個名稱會導致含糊不清。

在你的情況下,具有類BC 3名static數據成員,D不會造成任何問題和type_每個類的實例將與所有其他不同。僅僅因爲它們具有相同的名稱並不意味着C++將它們視爲覆蓋;只有virtual成員函數可以被覆蓋。

在每個類及其成員函數的上下文中,對name_的任何引用將始終引用該類中的name_,因爲類會隱藏其任何基類中的名稱,因此編譯器只會查看當前類。全球範圍內,你可以參考他們的完全合格的名稱name_領域,如A::name_B::name_

更重要的是,你在這裏使用,無論是虛擬的還是非虛擬的,並不重要,因爲所有繼承類型這裏問題在於變量的命名。由於每個static數據成員只有一個副本,因此您的類D最終是否繼承了A::name_的兩個副本是沒有任何問題的;它不能繼承兩個副本,因爲只有一個存在。

+0

感謝templatetypedef花時間對基本機制進行了解釋,我有點失落,並確信它不起作用。 – CLO 2011-03-05 11:25:26

0

沒有什麼含糊不清的。您將能夠參考這兩個字段B::type_C::type_

-1

在鑽石繼承中,C++標準提供了一種解決方案,以避免模糊不清。

您的類定義的結構看起來像

     A 
        /\ 
        / \ 
        / \ 
        B  C 
        \ /
        \ /
         \/
         D 

喜歡現在,當你繼承類B中使用下列

class B : public virtual A 

類C.同樣的事情

所以當任何A級類繼承B類& C,那麼它將只有A類的一個實例。

無需爲D類虛擬繼承。它沒有任何作用。

d級的大小可能會像以前一樣,但是從B類變量訪問任何地址時,你如果你在一個方法Dtype_創建D.

+1

-1這是對虛擬繼承的很好的描述,但我不認爲它回答了這裏提出的問題。 – templatetypedef 2011-03-05 11:12:44

+0

不管怎樣,我意識到虛擬繼承模式,但這確實不是我的問題。 Sed – CLO 2011-03-05 11:23:00

0

的情況下& C級將是一樣的,將解析爲Dtype_。如果您編寫A::name_B::name_,它將解析爲相應實例的type_

在另一個筆記上,似乎您可能試圖在C++中破解某種反射系統,因爲您在每個類中都有一個名爲type_的靜態字段。這在某些罕見的情況下可能有用,但這可能是一個壞主意。

+0

'type_'變量都是'static',所以不同對象的單個實例將不會有任何字段的副本。它們只是全局範圍內的全局範圍,並且不參與課堂布局。 – templatetypedef 2011-03-05 11:36:51

+0

我沒有看到他們是'靜態'。我現在改變了我的答案。 – 2011-03-05 11:42:40