2017-08-01 179 views
0

我試圖實現以下繼承關係。聯盟虛擬繼承

  Variable 
    /  \ 
... GlobalVar LocalVar ... 
     \  /(either) 
     ExtendedVar // Essentially with more fields 

我基本上希望它延長Variable子類中的一個,而選擇在運行時做出。虛擬繼承並不能完全解決問題。如果ExtendedVar繼承GlobalVarLocalVar,並且當我需要調用某個成員funciton時,我無法指定要爲該函數使用哪個基類。

此代碼似乎工作。

class ExtendedVar : public Variable /* ExtendedVar is-a Variable */ { 
    Variable& var; // wraps a var in it. This is the var to extend. 
    std::string some_field; 
} 

但它在繼承中帶有一個不必要的副本。或者我可以再多上幾門課,例如ExtendedGlobalVarExtendedLocalVar,這對維護顯然是不利的。

有沒有更好的選擇?

+1

https://stackoverflow.com/questions/49002/prefer -composition-over-inheritance – CoryKramer

+1

這實際上並不十分清楚你想要做什麼,但是你可能需要''D''中的成員'A *'(或者某個智能變體或'A&')而不是繼承。 –

+0

@CoryKramer,感謝您的鏈接,但我希望A的全部接口,並擴展A的子類之一... – YiFei

回答

2

我基本上想要它擴展變量的一個子類,並在運行時進行選擇。

要有運行時多態性,必須間接引用一個對象。基地不能是間接的,但常規的會員可以。因此,你認爲繼承是不可能的,但組成爲:

struct ExtendedVar { 
    std::unique_ptr<Variable> var; 
}; 

或者,我可以有幾類,如ExtendedGlobalVar和ExtendedLocalVar,這顯然不利於maintainence。

如果這是一個選項(即使是不好的選項),那麼它聽起來像基地的選擇不必在運行時完成。

在這種情況下,你可以用一個模板來生成與您所選擇的基類,而不必單獨維護每個變種:

template <class Base> 
struct ExtendedVar : Base { 
    // things common to all extended variables 
}; 

ExtendedVar<GlobalVar> an_extended_global_variable; 
+0

CRTP似乎在這裏做的伎倆。非常感謝。 – YiFei

+0

等等......我可以爲模板化的ExtendedVar有一個通用的基類嗎? – YiFei

+0

@YiFei哎呀。我所展示的不是CRTP:D它只是一個普通的模板。採用這種方法,只要模板參數繼承公共基礎,那麼類將從模板實例化。沒有編譯時檢查,但應該可以使用'enable_if'。 – user2079303