2010-08-04 63 views
0

我有一個通用的項目列表類來創建使用它作爲基類,像這樣一個更具體的上市..功能的參數繼承覆蓋

ref class ItemBase { } 
ref class ItemA : ItemBase { } 
ref class ItemList abstract { 
public: 
    virtual void add(ItemBase ^p); 
} 
ref class ItemListA : ItemList { 
public: 
    virtual void add(ItemA ^p) override; // it doesn't works :(
} 

我想restric添加特定類型的每個項目類。

+2

不要使用代碼標記代碼 - 只需將代碼縮進4個空格或選擇它並使用「010」按鈕。還要注意C++和C++/CLI是不同的語言。 – 2010-08-04 03:34:05

+2

您需要爲此使用泛型或遏制而不是繼承。不能使用繼承,因爲您違反了LSP。 – 2010-08-04 04:06:22

回答

2

這樣做的接受圖案使基類方法protected

ref class ItemBase { } 
ref class ItemA : ItemBase { } 
ref class ItemList abstract { 
protected: 
    virtual void addInternal(ItemBase ^p); 
} 
ref class ItemListA : ItemList { 
public: 
    virtual void add(ItemA ^p){addInternal(p);} 
} 

這裏是使用泛型更好的解決方案。請注意,我們如何將通用參數T限制爲ItemBase,以強制該集合只能與ItemBase或其子類一起使用。

ref class ItemBase { }; 
ref class ItemA : public ItemBase { }; 

generic <class T> 
where T: ItemBase 
ref class ItemList abstract { 
public: 
    virtual void Add(T p){} 
}; 

ref class ItemListA : ItemList<ItemA^> { 
    //no need to override Add here 
}; 

//usage 
int main(array<System::String ^> ^args) 
{ 
    ItemListA^ list = gcnew ItemListA(); 
    list->Add(gcnew ItemA()); 
} 
+0

不起作用,因爲函數參數不是協變的。 'addInternal'的合同是它接受任何'ItemBase'對象。派生類可以放寬合約,但他們絕不能拒絕接受對基類版本有效的參數。好吧,它會按照你的方式工作,但如果你要編寫包裝函數,你應該使用包容而不是繼承。請注意,另一個類仍然可以從'ItemListA'派生,直接調用'addInternal',並打破不變。 – 2010-08-04 04:07:57

+0

我同意,這是一個非常不合理的例子,因爲你通常會使基類成爲通用的。不過,它確實解決了OP的原始問題,雖然有點不明智。也許我有點急於宣佈它是一個被接受的適配器;) – 2010-08-04 04:33:58

+0

它的工作原理!感謝:P – grilix 2010-08-04 05:34:03