【问题标题】:How can I create a vector of derived objects?如何创建派生对象的向量?
【发布时间】:2020-09-30 03:27:48
【问题描述】:

我已经阅读了该网站上的几篇文章,但我仍然无法弄清楚创建来自不同派生类的对象 std::vector 的正确方法是什么。

我创建了一个类Column

template <typename T> class Column {
public:
    Column();
    virtual ~Column();
    vector<T>& getData();
    string getName();
    virtual string getType();

protected:
    string _name;
    vector<T> _data;
};

以及许多不同的派生类,例如:

class IntColumn : public Column<int> {
public:

    IntColumn();
    IntColumn(string name);
    ~IntColumn();
    vector<int> & getData();
    void addElement(int elem_to_add);
    string getType();

private:
    // ...
};

我现在需要做的是创建一个列向量,它可以是IntColumns、FloatColumns 等... (在我的脑海中,它可能类似于vector&lt;Column&gt; vect;,但我不能这样做,因为 Column 是一个模板类。)

我的最后一个问题是:哪种方法是正确的?

【问题讨论】:

  • 保留一个指向基类的指针向量,并插入派生类的实例。
  • 所有派生类都将继承Column的同一个实例化,还是可以不同?
  • 你可以有一个普通类作为Column的基类。将基类中的虚函数放到Column中。
  • 你不能创建不同对象的向量,这根本不是 C++ 的工作方式。正如@Ron 指出的那样,您只能拥有一个指向基类的指针向量。

标签: c++ c++11 templates inheritance stl


【解决方案1】:

首先,您缺少一个基类。 Column 是一个模板,而不是一个类,并且在模板中包含虚拟方法很少有用。

class Column {
public:
    Column();
    virtual ~Column() {}
    std::string getName() const { return _name; }
    virtual std::string getType();

protected:
    std::string _name;
};

template <typename T> class ColumnImpl : public Column {
public:
    ColumnImpl();
    std::vector<T>& getData() { return _data; }
    std::vector<T> const& getData() const { return _data; }

protected:
    std::vector<T> _data;
};

现在你可以做

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

存储(拥有)指向Column 实例的指针。

【讨论】:

  • 非常感谢!现在我还有 3 个问题: - 为 ColumnImpl 创建一个新的头文件会更“正确”和整洁吗? - 我不明白为什么我需要创建一个新类,为什么我的 Column 是一个模板,而不是一个类? (您可以将我链接到一个站点以了解其中的区别) - 为什么不将虚拟方法放入 ColumnImpl?
  • 那我应该从ColumnImpl继承所有的IntColumnFloatColumnCharColumn等类吗?
  • 目前尚不清楚最终目标是什么,因此无法提供进一步的建议。 IntColumn 可能只是 typedef'd 到 ColumnImpl&lt;int&gt;
  • 我正在使用它来完成我的教授给我的家庭作业(不幸的是,他完全不接受质疑)。最终目标是创建一个“模拟”SQL 语言的程序,所以我试图创建一个由不同的Columns 组成的表,这样每次我必须添加一条记录时,我都会在我的向量中添加元素@ 987654333@...
【解决方案2】:

向量与所有其他标准容器一样是同质的。容器的所有元素都属于同一类型。因此,一个元素的类型不能与另一个元素不同。一个向量的所有元素都可以是IntColumns,或者另一个向量的所有元素都可以是FloatColumns,但你不能在一个向量中混合和匹配不同的元素类型。

这个问题可以通过间接的魔法来解决。有几种选择:

  1. 使用指向公共基址的指针向量。这样,向量不包含对象,而是包含的指针指向其他地方的对象。您可以使用std::unique_ptr 等智能指针将指向对象的生命周期绑定到指针。

    但是,这只适用于不同类型具有共同基础的情况。但是你的类没有共同的基础。

  2. 使用标记联合的向量,例如std::variant。这种方法不需要继承,但仅限于有限的替代类型集。

  3. 使用不受约束的类型擦除,例如void*std::any 的向量。这允许被指向的元素具有任何对象类型,但是对对象没有太多可以做的事情。我还没有遇到过这方面的实际用例。

【讨论】:

  • 所以如果我想拥有 3 种以上的类型,并且还要将我的 Column 类保留为模板类,那么没有解决方案,对吗?
  • @JohnBardeen 一个解决方案是添加一个公共基础。
猜你喜欢
  • 1970-01-01
  • 2017-02-26
  • 2014-09-07
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多