可以具有 3 种不同数据类型 C++ 的向量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26208918/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:33:15  来源:igfitidea点击:

Vector that can have 3 different data types C++

c++vectorpolymorphism

提问by Jonny Forney

I'm trying to make a vector in C++ that can store 3 different data types. I do not want to use the boost library. Something like:

我正在尝试用 C++ 制作一个可以存储 3 种不同数据类型的向量。我不想使用 boost 库。就像是:

vector<type1, type2, type3> vectorName; 

Do I need to make a template? And if yes how would I do that?

我需要制作模板吗?如果是的话,我该怎么做?

回答by ApproachingDarknessFish

EDIT: as of C++17, the standard library now includes the class template std::variant, which is quite similar to pre-existing solutions in boost. variantis a type safe alternative to unions that allows multiple types to be joined using an "or" relationship, e.g., an std::variant<type1, type2, typ3>contains either a type1OR a type2OR a type3.It can be composed with std::vectorto yield exactly what you've described:

编辑:从 C++17 开始,标准库现在包括类模板std::variant,它与 boost 中预先存在的解决方案非常相似。variant是联合的类型安全替代方案,它允许使用“或”关系连接多个类型,例如, anstd::variant<type1, type2, typ3>包含 a type1OR a type2OR atype3.它可以组合std::vector以产生您所描述的内容:

std::vector<std::variant<type1, type2, type3>> vectorName; 

However, std::variantdoes introduce some restrictions. It cannot hold reference or array types, for example, and the underlying type (i.e. type1or type2) can only be accessed by template code. If std::variantdoes not permit the specific behavior you need, keep reading for a more complicated but more versatile approach that also has the benefit of working in any version of C++.

但是,std::variant确实引入了一些限制。例如,它不能保存引用或数组类型,并且只能通过模板代码访问底层类型(即type1type2)。如果std::variant不允许您需要的特定行为,请继续阅读更复杂但更通用的方法,该方法也具有在任何版本的 C++ 中工作的好处。

ORIGINAL ANSWER:

原始答案:

The easiest way to store multiple types in the same vector is to make them subtypes of a parent class, wrapping your desired types in classes if they aren't classes already.

在同一个向量中存储多个类型的最简单方法是使它们成为父类的子类型,如果它们不是类,则将所需的类型包装在类中。

class Parent
{
  //anything common to the types should be declared here, for instance:
  void print() //make this virtual if you want subclasses to override it
  {
     std::cout << "Printing!";
  }

  virtual ~Parent(); //virtual destructor to ensure our subclasses are correctly deallocated
};

class Type1 : public Parent
{
    void type1method();
};

class Type2 : public Parent
{
    void type2Method();
};


class Type3 : public Parent
{
    void type3Method();
};

You can then create a vector of Parentpointers that can store pointers to the child types:

然后,您可以创建一个Parent可以存储指向子类型的指针的指针向量:

std::vector<Parent*> vec;

vec.push_back(new Type1);
vec.push_back(new Type2);
vec.push_back(new Type3);

When accessing elements directly from the vector, you'll only be able to use members that belong to Parent. For instance, you can write:

直接从向量访问元素时,您将只能使用属于Parent. 例如,您可以编写:

vec[0]->print();

But not:

但不是:

vec[0]->type1Method();

As the element type has been declared as Parent*and the Parenttype has no type1Method.

由于元素类型已声明为Parent*,并且Parent类型没有type1Method.

If you need to access the subtype-specific members, you can convert the Parentpointers to subtype pointers like so:

如果您需要访问特定于子类型的成员,您可以将Parent指针转换为子类型指针,如下所示:

Parent *p = vec[0];

Type1 *t1 = nullptr;
Type2 *t2 = nullptr;
Type3 *t3 = nullptr;

if (t1 = dynamic_cast<Type1*>(p))
{
    t1->type1Method();
}
else if (t2 = dynamic_cast<Type2*>(p))
{
    t2->type2Method();
}
else if (t3 = dynamic_cast<Type3*>(p))
{
    t3->type3Method();
}

Although it's generally considered a better idea to avoid this kind of explicit type-branching and instead rely on virtual methods.

尽管通常认为避免这种显式类型分支并依赖虚拟方法是一个更好的主意。

Be sure to delete the pointers before removing them from the vector if you use dynamic allocation, as I did in the example above. Alternatively, use smart pointers (probably std::unique_ptr) and let your memory take care of itself:

如果您使用动态分配,请确保在将指针从向量中删除之前删除指针,就像我在上面的示例中所做的那样。或者,使用智能指针(可能std::unique_ptr)并让您的记忆自行处理:

std::vector<std::unique_ptr<Parent>> vec;

回答by Pawe? Stawarz

I'm trying to make a vector in C++ that can store 3 different data types.

我正在尝试用 C++ 制作一个可以存储 3 种不同数据类型的向量。

The answer here really depends on the particular use case:

这里的答案实际上取决于特定的用例:

  1. If the objects are somehow connected and similar in some fashion - create a base class and derive all the classes from it, then make the vector store unique_ptrs to the parent class (see ApproachingDarknessFishs answer for details),

  2. If the objects are all of fundamental (so built-in) types - use an unionthat groups the types and define a vector<yourUnionType>,

  3. If the objects are of unknown type, but you're sure they share a similiar interface, create a base class, and derive a templated child class from it (template <typename T> class container: public parent{};), and create a vector<unique_ptr<parent>>like in the first case,

  4. If the objects are of types that for some reason cannot be connected (so for example the vectorstores int, std::string, and yourType), connect them via an union, like in 2. Or - even better...

  1. 如果对象以某种方式以某种方式连接和相似 - 创建一个基类并从中派生所有类,然后将向量存储unique_ptrs 到父类(有关详细信息,请参阅ApproachingDarknessFish的答案),

  2. 如果对象都是基本(内置)类型 - 使用union对类型进行分组并定义一个vector<yourUnionType>,

  3. 如果对象是未知类型,但您确定它们共享一个相似的接口,创建一个基类,并从中派生一个模板化的子类 ( template <typename T> class container: public parent{};),并vector<unique_ptr<parent>>在第一种情况下创建一个类似的,

  4. 如果对象是,由于某种原因不能被连接的类型(从而例如vector商店intstd::stringyourType),通过将它们连接起来union,像2。或者——甚至更好……

...if you have time and want to learn something - look how boost::anyis implemented and try implementing it yourself, if you really don't want to use the library itself. It's not as hard as it may seem.

...如果你有时间并想学习一些东西 -boost::any如果你真的不想使用库本身,看看它是如何实现的并尝试自己实现它。这并不像看起来那么难。

回答by stephane k.

you could use std::any, store your objects in the vector as any and when you pull them out use type() == typeid(mytype)

您可以使用 std::any,将您的对象作为任何对象存储在向量中,当您将它们拉出时,请使用 type() == typeid(mytype)

https://en.cppreference.com/w/cpp/utility/any

https://en.cppreference.com/w/cpp/utility/any

This is only for C++17 onwards though.

不过,这仅适用于 C++17。

回答by FunkMasterP

Does it have to be a vector? You might just consider a linked list of generic type, then iterate through that list, use typeid() to figure out the data type of the node and pull the data with a node.get() function.

它必须是一个向量吗?您可能只考虑泛型类型的链表,然后遍历该列表,使用 typeid() 找出节点的数据类型并使用 node.get() 函数提取数据。