C++:模板类的向量

Jak*_*ain 9 c++ generics vector

我有一个名为Cell的模板类如下: -

template<class T>class Cell
{
    string header, T data;
}
Run Code Online (Sandbox Code Playgroud)

现在我想要另一个名为Row的类.Row将有一个名为Cells的向量,以便我可以将Cell和Cell类型元素添加到该向量.可能吗?

如果是这样,我该怎么做?提前致谢.

Ski*_*izz 17

通过您提供的额外细节,前两个答案将无效.你需要的是一种被称为细胞变体的类型,然后你可以有一个矢量.例如:-

enum CellType
{
  Int,
  Float,
  // etc
};

class Cell
{
  CellType type;
  union
  {
    int i;
    float f;
    // etc
  };
};

class Vector
{
  vector <Cell> cells;
};
Run Code Online (Sandbox Code Playgroud)

然而,添加新类型是一件痛苦的事情,因为它需要大量的代码来维护.替代方案可以使用具有公共基类的单元格模板: -

class ICell
{
  // list of cell methods
};

template <class T>
class Cell : public ICell
{
  T data;
  // implementation of cell methods
};

class Vector
{
  vector <ICell *> cells;
};
Run Code Online (Sandbox Code Playgroud)

这可能会更好,因为您最初需要更少的代码来更新以添加新的单元格类型,但您必须在单元格向量中使用指针类型.如果按值存储单元格vector <ICell>,则由于对象切片而丢失数据.

  • Icell 不能用于访问封装的数据。而且您无法在基类中定义虚函数来提供对数据的访问,因为您将“typename T”在类层次结构中向上移动,并且您将再次面临相同的问题,即定义 vector&lt;Icell&lt;T&gt;&gt;细胞; 这是不允许的。因此我认为这不是正确的答案 (3认同)
  • +1。union 不仅是痛苦,而且也不是类型安全的,而这正是模板的全部目的。 (2认同)

xua*_*g84 8

之所以这是不可能在C++中,但可能是Java/Python是因为:在C++载体,在STL容器的存储(由矢量::数据()返回)包含了所有的对象实例sequencially包装.其中每个元素必须具有相同的大小.这使得寻址快速方便.因此,假设您定义了模板类A,

template <class T>
class A{
  int id;
  T obj;
};
Run Code Online (Sandbox Code Playgroud)

其大小取决于模板变量"T obj".推动不同模板类型T的相同类A将使向量中的每个元素具有不同的大小,因此,这是不可能的.唯一的方法是使用基类的shared_ptr或unique_ptr的向量.C++ 11和Boost都支持shared_ptr和unique_ptr.每个派生类元素可以具有不同的模板类型.这样,当调用基类指针的析构函数时,将调用派生类的析构函数.例如,

#include <memory>
#include <vector>
#include <iostream>
#include <string>

using namespace std;

class A{};

template <class T>
class AImpl : public A{
public:
    T obj;
    AImpl(T _obj):obj(_obj){}
    ~AImpl(){
        cout << "Deleting " << obj << endl;
    }
};

int main(int argc, char** argv)
{
    AImpl <string>* a1 = new AImpl <string> ("string1234");
    AImpl <int>* a2 = new AImpl <int> (1234);
    AImpl <double>* a3 = new AImpl <double> (1.234);
    vector <shared_ptr<A>> As;
    As.push_back(shared_ptr<A>(a1));
    As.push_back(shared_ptr<A>(a2));
    As.push_back(shared_ptr<A>(a3));
}
Run Code Online (Sandbox Code Playgroud)

请记住使用-std = c ++ 11进行编译以启用C++ 11.

输出:

Deleting string1234
Deleting 1234
Deleting 1.234
Run Code Online (Sandbox Code Playgroud)

而你得到你想要的!:)

在Java/Python中,每个类对象变量实际上都是一个指针,因此,A的Java数组或A的Python列表等同于A的C++指针数组.因此,如果没有明确创建,您将获得基本相同的功能shared_ptrs.


For*_*veR 6

像这样的东西?

template<class T>
class Row
{
private:
   std::vector<Cell<T> > cells;
};
Run Code Online (Sandbox Code Playgroud)

好的,这个答案是不正确的.

所以,如果你想存储在一个vector不同的单元格中 - 你应该使用一些动态类型标识(你可以使用一个基类并在向量中存储指向它的指针,它只使用虚拟函数,在所有派生类中都被覆盖,你可以存储类似的东西boost::anytype-identification为每个插入的元素保存一些,用于将它们转换为实际类型并使用它).


Ela*_*zar 6

另一个答案是好的,但你可能想要:

template<class T>
class Row
{
private:
    class Cell {
        string header;
        T data;
    }

    std::vector<Cell> cells;
    ...
}
Run Code Online (Sandbox Code Playgroud)