2010-08-10 69 views
1

我從來沒有見過用作虛擬和非虛擬基礎的類(即,如果某個類旨在成爲祖先,那麼我們通常事先知道關於繼承的類型 - 虛擬還是非虛擬)。是基類列表表示虛擬繼承的正確位置?

所以我想在C++中存在一個容易出錯的自由來專門化基類列表中的「虛擬」繼承。它應該更好地指定爲「虛擬」的基類本身

或者也許我錯了?

如果否,是否有人可以描述一些技術來防止意外的非虛擬繼承這樣的「虛擬」類?

或者在即將到來的C++標準中有一些觀點嗎?

(很抱歉,如果一式兩份)


一些實例

1)ReferenceCounted類作爲基礎,一些-計數基於引用智能指針可以指向所有類。我們需要防止這些基本實例(和引用計數器)的重複。除了優化之外,沒有理由將此類用作非虛擬基礎。

2)的接口層次結構和實現 (接口分層結構必須是在這種情況下「虛擬」)

 
// interfaces: 

struct BaseIface{ 
    void virtual func()=0; 
}; 

struct DerivedIface: public virtual BaseIface{ 
    void some_another_func()=0; 
} 


// implementations 

class BaseImpl: public virtual BaseIface{ 
    void virtual func(){....}; 
} 

class DerivedImpl: public BaseImpl, public virtual DerivedIface{ 
    void some_another_func(){...}; 
} 

我懷疑在許多情況下,非虛繼承不是一個概念需要的對應的層次結構中,它僅用於減少虛擬繼承開銷(有時爲了能夠static_cast <>驅動:)

請注意,Java僅用於接口的虛擬(在C++方面)繼承,並且我不知道任何抱怨這種語言缺乏「非虛擬」(這是本質的表達能力不如C++,但這個「功能」不是它的主要缺點:)。

回答

1

在基類中你沒有什麼辦法可以做到這一點(你也不會真的想)。爲虛擬和非虛擬繼承使用基類是完全合理的。

你真的想要應該指定在大多數派生類中的虛擬繼承,其中當前必須在中間類中指定。不幸的是,我沒有看到太多的方法 - 即使當一個類從兩個(或更多)其他類都有一個共同的基類派生出來時,虛擬繼承變得必要(主要),但虛擬繼承真正控制了另外兩個類是編譯的,所以如果你(只)在最派生類中指定它,你最終會得到類似export的東西,你可能需要返回並重新編譯那些基於派生類最多的中間類虛擬繼承(並且有一些方法來存儲中間類,這兩種方法都可以用於兩種方式)。

+0

你剛纔描述與「懶」虛擬繼承和解決的問題是 使用「nonlazy」之一,即定義「虛擬」的最基礎(不是大多數派生)類 不過,我也許應該更好地解釋我的意圖,所以我在我的問題中增加了一些例子。 – user396672 2010-08-10 16:48:16