可以具有 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
Vector that can have 3 different data types C++
提问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. variant
is 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 type1
OR a type2
OR a type3.
It can be composed with std::vector
to yield exactly what you've described:
编辑:从 C++17 开始,标准库现在包括类模板std::variant,它与 boost 中预先存在的解决方案非常相似。variant
是联合的类型安全替代方案,它允许使用“或”关系连接多个类型,例如, anstd::variant<type1, type2, typ3>
包含 a type1
OR a type2
OR atype3.
它可以组合std::vector
以产生您所描述的内容:
std::vector<std::variant<type1, type2, type3>> vectorName;
However, std::variant
does introduce some restrictions. It cannot hold reference or array types, for example, and the underlying type (i.e. type1
or type2
) can only be accessed by template code. If std::variant
does 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
确实引入了一些限制。例如,它不能保存引用或数组类型,并且只能通过模板代码访问底层类型(即type1
或type2
)。如果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 Parent
pointers 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 Parent
type has no type1Method
.
由于元素类型已声明为Parent*
,并且Parent
类型没有type1Method
.
If you need to access the subtype-specific members, you can convert the Parent
pointers 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:
这里的答案实际上取决于特定的用例:
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_ptr
s to the parent class (see ApproachingDarknessFishs answer for details),If the objects are all of fundamental (so built-in) types - use an
union
that groups the types and define avector<yourUnionType>
,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 avector<unique_ptr<parent>>
like in the first case,If the objects are of types that for some reason cannot be connected (so for example the
vector
storesint
,std::string
, andyourType
), connect them via anunion
, like in 2. Or - even better...
如果对象以某种方式以某种方式连接和相似 - 创建一个基类并从中派生所有类,然后将向量存储
unique_ptr
s 到父类(有关详细信息,请参阅ApproachingDarknessFish的答案),如果对象都是基本(内置)类型 - 使用
union
对类型进行分组并定义一个vector<yourUnionType>
,如果对象是未知类型,但您确定它们共享一个相似的接口,创建一个基类,并从中派生一个模板化的子类 (
template <typename T> class container: public parent{};
),并vector<unique_ptr<parent>>
在第一种情况下创建一个类似的,如果对象是,由于某种原因不能被连接的类型(从而例如
vector
商店int
,std::string
和yourType
),通过将它们连接起来union
,像2。或者——甚至更好……
...if you have time and want to learn something - look how boost::any
is 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() 函数提取数据。