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

Storing classes inherited of a class template in a C++ Vector

本文关键字:C++Vector 存储 继承      更新时间:2023-10-16

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

不幸的是,在C++中,如果不指定其参数(类似于std::vector<MyClassTemplate<?,?>> myVector;(,就不可能定义MyClassTemplate的向量。

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

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

我从您的问题中了解到什么:

  • 您有一个模板类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对象(因为它们在这里有一个纯虚拟函数,所以无法创建(,如果可以创建,它们将对您放入的派生对象进行切片(即,它们有丢失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,请确保这些派生自预期的抽象类型

在线演示(带智能指针(

如果我理解正确,你想要这样的东西:

template <class T>
struct S { void f(); };
std::vector<S> v;

其中CCD_ 14可以包含来自CCD_ 15的任何实例化。您将无法。S<>是一个类模板。您可以将其视为类型的生成器。从S<>生成的每种类型都是不同的:S<int>S<float>intfloat本身一样不同。

如果你想拥有任何S<>的容器,你需要玩多态卡:

struct base
{
    virtual ~base() = default;
    virtual void f() = 0;
};
template <class T>
struct S : base
{
    void f() override
    {
        std::cout << typeid(T).name() << "n";
    }
};

int main()
{
    std::vector<std::unique_ptr<base>> v;
    v.push_back(std::make_unique<S<int>>());
    v.push_back(std::make_unique<S<float>>());
    v.push_back(std::make_unique<S<char>>());
    for (auto&& s : v)
        s->f();
}

输出:

int
float
char