[英]C++ templates and inheritance
我的C ++框架有Buttons。 Button来自Control。 因此,接受Control的函数可以将Button作为其参数。 到现在为止还挺好。
我也有List <
T>。 但是,List <
Button>不是从List <
Control>派生的,这意味着接受控件列表的函数不能将Buttons列表作为其参数。 这很不幸。
也许这是一个愚蠢的问题,但我不知道如何解决这个问题:( List <
Button >
应该来自List <
Control >
,但我没有看到一种方法来“自动”实现这一点。
Stroustrup在他的FAQ中有一个项目:
为什么我不能将vector<Apple*>
指定给vector<Fruit*>
您可以通过两种方式解决它:
Control
指针。 然后接受List<Control*>
List<Button>
和List<Control>
,但它更多的是样板代码,而不是大多数时候的neopssary。 这是第二种替代方案的代码。 第一种选择已经由其他答案解释:
class MyWindow {
template<typename T>
void doSomething(List<T> & l) {
// do something with the list...
if(boost::is_same<Control, T>::value) {
// special casing Control
} else if(boost::is_same<Button, T>::value) {
// special casing Button
}
}
};
要仅为List<derived from Control>
限制doSomething
,需要更多代码(如果您想知道,请查找enable_if
)。
请注意,这种代码(看你有什么类型)是要避免的。 你应该用虚函数来处理这些事情。 添加一个函数doSomething
to Control,并在Button中覆盖它。
使用指针怎么样? 只需要一个列表list<Control*>
,并将您喜欢的任何Control派生对象放入其中。
我不想告诉你,但是如果你使用Control实例列表而不是指向Control的指针,你的按钮无论如何都会是垃圾(Google“对象切片”)。 如果他们是指针列表,然后可以使list<button*>
到list<control*>
正如其他人的建议,或做一个拷贝到一个新的list<control*>
从list<button*>
并传递进入功能而不是。 或者将该功能重写为模板。
因此,如果您之前有一个名为doSomething的函数,它将控件列表作为参数,那么您将其重写为:
template <class TControl>
void doSomething( const std::list<TControl*>& myControls ) {
... whatever the function is currently doing ...
}
void doSomethingElse() {
std::list<Button*> buttons;
std::list<Control*> controls;
doSomething( buttons );
doSomething( controls );
}
而不是使用List <Button>,使用List <Control *>,它们指向Buttons。这样,您的函数只需要采用一种类型:List <Control *>。
通常,编写在列表,序列,...上执行的算法的C ++方法是提供迭代器作为参数。
template < class iterator >
doSomething(iterator beg, iterator end);
这解决了List <Button *>不是从List <Control *>派生的。 (使用模板List <T *>也会,但这会让你的函数变得通用 - 但不是真的)
根据我的经验,在迭代器上运行良好的模板化函数可能会有很多(太多......)工作,但它是“C ++方式”......
如果你走这条路,考虑使用Boost.ConceptCheck 。 它会让你的生活更轻松。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.