C ++一个std :: vector包含多种类型的模板类 [英] C++ One std::vector containing template class of multiple types

查看:57
本文介绍了C ++一个std :: vector包含多种类型的模板类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在一个向量中存储多种类型的模板类.

I need to store multiple types of a template class in a single vector.

例如,用于:

template <typename T>
class templateClass{
     bool someFunction();
};

我需要一个向量来存储所有内容:

I need one vector that will store all of:

templateClass<int> t1;
templateClass<char> t2;
templateClass<std::string> t3;
etc

据我所知这是不可能的,如果有人可以说怎么做?

As far as I know this is not possible, if it is could someone say how?

如果不可能的话,有人可以解释如何进行以下工作吗?

If it isn't possible could someone explain how to make the following work?

作为一种变通方法,我尝试使用非模板基类,并从中继承模板类.

As a work around I tried to use a base, non template class and inherit the template class from it.

 class templateInterface{
     virtual bool someFunction() = 0;
 };

 template <typename T>
 class templateClass : public templateInterface{
     bool someFunction();
 };

然后我创建了一个向量来存储基本的"templateInterface"类:

I then created a vector to store the base "templateInterface" class:

std::vector<templateInterface> v;
templateClass<int> t;
v.push_back(t);

这产生了以下错误:

error: cannot allocate an object of abstract type 'templateInterface'
note: because the following virtual functions are pure within 'templateInterface'
note: virtual bool templateInterface::someFunction()

要解决此错误,我通过提供函数主体使templateInterface中的函数不是纯虚函数,该函数主体已编译,但是在调用函数时不使用覆盖,而是虚函数中的主体.

To fix this error I made the function in templateInterface not a pure virtual by providing a function body, this compiled but when calling the function the overide is not used, but instead the body in the virtual function.

例如:

 class templateInterface{
     virtual bool someFunction() {return true;}
 };

 template <typename T>
 class templateClass : public templateInterface{
     bool someFunction() {return false;}
 };

 std::vector<templateInterface> v;
 templateClass<int> i;
 v.push_back(i);
 v[0].someFunction(); //This returns true, and does not use the code in the 'templateClass' function body

是否有任何方法可以解决此问题,以便使用覆盖函数,或者还有另一种解决方法将多个模板类型存储在单个向量中?

Is there any way to fix this so that the overridden function is used, or is there another workaround to store multiple template types in a single vector?

推荐答案

为什么您的代码不起作用:

上调用虚拟函数不使用多态性.它调用为编译器看到的为此确切符号的类型定义的函数,而不是运行时类型.当您将子类型插入基本类型的向量中时,您的值将被转换到基本类型中(类型切片"),这不是您想要的.现在,在它们上面调用函数将调用为基本类型定义的函数,因为它不是该类型的 .

Calling a virtual function on a value doesn't use polymorphism. It calls the function which is defined for the type of this exact symbol as seen by the compiler, not the runtime type. When you insert sub types into a vector of the base type, your values will be converted into the base type ("type slicing"), which is not what you want. Calling functions on them will now call the function as defined for the base type, since not it is of that type.

如何解决此问题?

此代码段可以重现相同的问题:

The same problem can be reproduced with this code snippet:

templateInterface x = templateClass<int>(); // Type slicing takes place!
x.someFunction();  // -> templateInterface::someFunction() is called!

多态仅适用于 pointer reference 类型.然后,它将使用指针/引用后面的对象的运行时类型来决定要调用的实现(通过使用vtable).

Polymorphism only works on a pointer or reference type. It will then use the runtime type of the object behind the pointer / reference to decide which implementation to call (by using it's vtable).

就类型切片而言,转换指针是完全安全的".您的 actual 值将完全不会转换,多态性将按预期工作.

Converting pointers is totally "safe" with regard to type slicing. Your actual values won't be converted at all and polymorphism will work as expected.

示例,类似于上面的代码片段:

Example, analogous to the code snippet above:

templateInterface *x = new templateClass<int>();  // No type slicing takes place
x->someFunction();  // -> templateClass<int>::someFunction() is called!

delete x;  // Don't forget to destroy your objects.

载体如何?

因此,您必须在代码中采用这些更改.您只需将指针存储为向量中的实际类型,而不是直接存储值.

So you have to adopt these changes in your code. You can simply store pointers to actual types in the vector, instead of storing the values directly.

使用指针时,您还必须注意删除分配的对象.为此,您可以使用智能指针,它们会自动关心删除操作. unique_ptr 是一种这样的智能指针类型.每当超出范围(唯一所有权"-范围是所有者)时,它将删除该指针.假设对象的生命周期受作用域的约束,这就是您应该使用的方法:

When working with pointers you also have to care about deleting your allocated objects. For this you can use smart pointers which care about deletion automatically. unique_ptr is one such smart pointer type. It deletes the pointee whenever it goes out of scope ("unique ownership" - the scope being the owner). Assuming the lifetime of your objects is bound to the scope this is what you should use:

std::vector<std::unique_ptr<templateInterface>> v;

templateClass<int> *i = new templateClass<int>();    // create new object
v.push_back(std::unique_ptr<templateInterface>(i));  // put it in the vector

v.emplace_back(new templateClass<int>());   // "direct" alternative

然后,使用以下语法在这些元素之一上调用虚拟函数:

Then, call a virtual function on one of these elements with the following syntax:

v[0]->someFunction();

确保您将所有功能都设为 virtual ,这些功能应可能被子类覆盖.否则,将不会调用其覆盖的版本.但是,由于您已经引入了接口",所以我确定您正在使用抽象函数.

Make sure you make all functions virtual which should be possible to be overridden by subclasses. Otherwise their overridden version will not be called. But since you already introduced an "interface", I'm sure you are working with abstract functions.

替代方法:

要做的另一种方法是在向量​​中使用 variant 类型.有一些变体类型的实现, Boost.Variant 成为一个非常受欢迎的人.如果您没有类型层次结构(例如,存储原始类型时),则此方法特别好.然后,您将使用类似 std :: vector< boost :: variant< int,char,bool>>

Alternative ways to do what you want is to use a variant type in the vector. There are some implementations of variant types, the Boost.Variant being a very popular one. This approach is especially nice if you don't have a type hierarchy (for example when you store primitive types). You would then use a vector type like std::vector<boost::variant<int, char, bool>>

这篇关于C ++一个std :: vector包含多种类型的模板类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆