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

Vector that can have 3 different data types C++(可以具有 3 种不同数据类型 C++ 的向量)
本文介绍了可以具有 3 种不同数据类型 C++ 的向量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

限时送ChatGPT账号..

我正在尝试用 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 确实引入了一些限制.例如,它不能保存引用或数组类型,并且只能通过模板代码访问底层类型(即 type1type2).如果 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++ 的向量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

OpenGL transforming objects with multiple rotations of Different axis(OpenGL 变换不同轴多次旋转的对象)
GLFW first responder error(GLFW 第一响应者错误)
SOIL not linking correctly(SOIL 连接不正确)
Core profile vs version string? Only getting GLSL 1.3/OGL 3.0 in mesa 10.0.1(核心配置文件与版本字符串?在 mesa 10.0.1 中只获得 GLSL 1.3/OGL 3.0)
What is the range of OpenGL texture ID?(OpenGL 纹理 ID 的范围是多少?)
How taxing are OpenGL glDrawElements() calls compared to basic logic code?(与基本逻辑代码相比,OpenGL glDrawElements() 调用的繁重程度如何?)