我在这个网站上看了好几个帖子,但我还是搞不清楚什么是正确的创建派生对象向量的方法。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:
// ...
};
我现在要做的是创建一个列的向量,可以是: IntColumn
s, FloatColumn
的,等等......(在我的脑海里,应该是这样的。vector<Column> vect;
但我不能这样做,因为Column是一个模板类)。)
我最后的问题是:哪种方法是正确的?
首先,你缺少一个基类。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
实例。
矢量,像所有其他标准容器一样是同质的。容器的所有元素都是相同的类型。因此,一个元素不能与另一个元素的类型不同。一个向量的所有元素可以是 IntColumns
或另一个向量的所有元素可以是 FloatColumns
但你不能在一个向量中混合和匹配不同的元素类型。
这个问题可以通过间接的方法来解决。有几种选择。
使用一个指向公共基础的指针向量。这样向量并不包含对象,而是包含的指针指向其他地方的对象。你可以通过使用智能指针将指向的对象的寿命绑定到指针上,如 std::unique_ptr
.
然而,这只有在不同类型有一个共同的基础时才有效。但是你的类没有一个共同的基础。
使用一个标记联合的向量,如 std::variant
. 这种方法不需要继承,但仅限于有限的备选类型集。
使用不受限制的类型擦除,如向量的 void*
或 std::any
. 这就允许指向的元素具有任何对象类型,但对对象的处理并不多。我还没有遇到实际的使用案例。