2010-08-04 128 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