在C ++ Vector中存储继承类模板的类

时间:2016-08-23 15:47:38

标签: c++ templates inheritance vector interface

我想在类向量中存储派生类模板MyClassTemplate的类。

不幸的是,在C ++中,无法定义MyClassTemplate的向量而不指定其参数(类似std::vector<MyClassTemplate<?,?>> myVector;)。

但是有一种可能的解决方案来定义一个非模板化的接口(只有纯虚函数的类)作为向量中项目的类型。 此接口由类模板继承。在我的例子中,类模板只有使用模板参数的成员,所以似乎只有一个空接口才是我的Vector的合适项目类型。

这个问题还有其他(更好的)解决方案吗?

1 个答案:

答案 0 :(得分:3)

我从您的问题中理解:

  • 您有一个模板类MyClassTemplate<class X, class Y>;
  • 您已经知道每个模板实例化(例如MyClassTemplate<A,B>MyClassTemplate<U,V>)是不同的不相关类型;
  • 但是你想把这种不相关的类型放在同一个向量中,以便能够使用通用接口并以多态方式使用向量元素。

如何解决这个问题?

首先,您可以定义一个常见的非模板祖先:

class MyCommonAncestor {
public:  
    virtual void common_operation1()=0;
    virtual ~MyCommonAncestor() {}
}; 

template <class X, class Y> 
class MyTemplateClass : public MyCommonAncestor {
    X myx; 
    Y myY; 
public:  
    void common_operation1() override; 
    X operation2(const Y& y); 
};

不幸的是,这样做实际上并不允许你使用vector<MyCommonAncestor>因为这样的向量只能保存MyCommonAncestor个对象(因为它们在这里有一个纯虚函数而无法创建)如果可以创建它们,它们会slice您放入的派生对象(即它们可能会丢失myXmyY

但是你可以创建一个指针向量。我在这里展示了一个简单的例子来说明,使用原始指针;但实际上你最好使用shared_ptr

vector<MyCommonAncestor*> myVector; 
myVector.push_back(new MyTemplateClass<A,B>); 
myVector.push_back(new MyTemplateClass<U,V>); 

然后,您可以根据MyCommonAncestor的界面迭代元素并应用常用函数。

挑战

当您想要调用依赖于模板参数的函数时,会发生挑战(例如operation2())。显然,这些不能包括在共同的祖先中,因为它们依赖于尚未定义的模板参数。

可能的解决方法:

  • 避免这些,只能通过常规操作(可以在模板中覆盖)间接调用这些函数。
  • 在通用接口中使用抽象类型的参数。通过指针或引用传递这些。稍后,对于A和B或U和V,请确保这些是从预期的抽象类型派生的。

<强> Online demo (with smart pointers)