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

问题描述 投票:0回答:1

我正在尝试使用C ++创建一个可以存储3种不同数据类型的向量。我不想使用Boost库。类似于:

vector<type1, type2, type3> vectorName; 

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

c++ class vector
1个回答
15
投票

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

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

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

原始答案:

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

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指针的向量,该向量可以存储指向子类型的指针:

std::vector<Parent*> vec;

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

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

vec[0]->print();

但不是:

vec[0]->type1Method();

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

如果需要访问特定于子类型的成员,可以将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();
}

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

如果使用动态分配,请像在上面的示例中所做的那样,在将指针从向量中删除之前,请务必先删除它们。或者,使用智能指针(可能是std::unique_ptr),让您的内存自理:

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

8
投票

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

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

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

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

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

  4. 如果对象的类型由于某种原因而无法连接(例如vector存储intstd::stringyourType),则通过union将它们连接,例如2。或者-甚至更好...

...。如果您有时间想要学习一些东西,请查看boost::any的实现方式,如果您真的不想使用库本身,请尝试自己实施。它并不像看起来那样难。


3
投票

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

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

虽然仅适用于C ++ 17以上。


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.