C++模板和继承

gga*_*ett 6 c++ inheritance templates

我的C++框架有Buttons.Button来自Control.因此,接受Control的函数可以将Button作为其参数.到现在为止还挺好.

我也有List <T>.但是,List <Button>不是从List <Control> 派生的,这意味着接受Controls列表的函数不能将Buttons列表作为其参数.这很不幸.

也许这是一个愚蠢的问题,但我不知道如何解决这个问题:(列表<按钮>应该来自List <Control >,但我没有看到一种方法来"自动"实现这一点.

Joh*_*itb 7

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中覆盖它.


MrZ*_*bra 6

使用指针怎么样?只需要一个列表,list<Control*>并将您喜欢的任何Control派生对象放入其中.


Mic*_*hel 6

我不想告诉你,但是如果你使用Control实例列表而不是指向Control的指针,你的按钮无论如何都会是垃圾(Google"对象切片").如果他们是指针列表,然后要么使list<button*>list<control*>如其他人所说,或者做一个拷贝到一个新的list<control*>list<button*>并通过入函数.或者将该功能重写为模板.

因此,如果您之前有一个名为doS​​omething的函数,它将控件列表作为参数,那么您将其重写为:

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)