问题描述
我正在尝试用 C++ 制作一个可以存储 3 种不同数据类型的向量.我不想使用 boost 库.类似的东西:
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:
vector<type1, type2, type3> vectorName;
我需要制作模板吗?如果是,我该怎么做?
Do I need to make a template? And if yes how would I do that?
推荐答案
从 C++17 开始,标准库现在包括类模板 std::variant,这与 boost 中预先存在的解决方案非常相似.variant
是联合的类型安全替代方案,允许使用或"连接多个类型.关系,例如,一个 std::variant
包含一个 type1
OR a type2
OR a type3.
它可以与 std::vector
组合以产生您所描述的内容:
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:
std::vector<std::variant<type1, type2, type3>> vectorName;
然而,std::variant
确实引入了一些限制.例如,它不能保存引用或数组类型,并且只能通过模板代码访问底层类型(即 type1
或 type2
).如果 std::variant
不允许您需要的特定行为,请继续阅读更复杂但更通用的方法,该方法也有在任何版本的 C++ 中工作的好处.
However, std::variant
does introduce some restrictions. For example, it cannot hold reference or array types, 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++.
原答案:
在同一个向量中存储多个类型的最简单方法是使它们成为父类的子类型,如果它们不是类,则将所需类型包装在类中.
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();
};
然后,您可以创建一个 Parent
指针向量,用于存储指向子类型的指针:
You can then create a vector of Parent
pointers that can store pointers to the child types:
std::vector<Parent*> vec;
vec.push_back(new Type1);
vec.push_back(new Type2);
vec.push_back(new Type3);
直接从向量访问元素时,您将只能使用属于Parent
的成员.例如,你可以写:
When accessing elements directly from the vector, you'll only be able to use members that belong to Parent
. For instance, you can write:
vec[0]->print();
但不是:
vec[0]->type1Method();
由于元素类型已声明为Parent*
,而Parent
类型没有名为type1Method
的成员.
As the element type has been declared as Parent*
and the Parent
type has no member named type1Method
.
如果您需要访问特定于子类型的成员,您可以将 Parent
指针转换为子类型指针,如下所示:
If you need to access the subtype-specific members, you can convert the Parent
pointers to subtype pointers like so:
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.
如果您使用动态分配,请确保在将指针从向量中删除之前删除指针,就像我在上面的示例中所做的那样.或者,使用智能指针(可能是 std::unique_ptr
)并让您的记忆自行处理:
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::vector<std::unique_ptr<Parent>> vec;
这篇关于可以具有 3 种不同数据类型 C++ 的向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!