gga*_*ett 6 c++ inheritance templates
我的C++框架有Buttons.Button来自Control.因此,接受Control的函数可以将Button作为其参数.到现在为止还挺好.
我也有List <T>.但是,List <Button>不是从List <Control> 派生的,这意味着接受Controls列表的函数不能将Buttons列表作为其参数.这很不幸.
也许这是一个愚蠢的问题,但我不知道如何解决这个问题:(列表<按钮>应该来自List <Control >,但我没有看到一种方法来"自动"实现这一点.
Stroustrup在他的FAQ中有一个项目:
为什么我不能指定vector<Apple*>一个vector<Fruit*>
您可以通过两种方式解决它:
Control.然后接受List<Control*>List<Button>和List<Control>再,但它更多的样板代码,而不是necassary的大部分时间.这是第二种替代方案的代码.第一种选择已经由其他答案解释:
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
}
}
};
Run Code Online (Sandbox Code Playgroud)
要doSomething仅限制List<derived from Control>,需要更多代码(enable_if如果您想知道,请查找).
请注意,这种代码(看你有什么类型)是要避免的.你应该用虚函数来处理这些事情.doSomething向Control 添加一个函数,并在Button中覆盖它.
我不想告诉你,但是如果你使用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 );
}
Run Code Online (Sandbox Code Playgroud)