我有一个名为Cell的模板类,代码如下:
template<class T>class Cell
{
string header, T data;
}
现在我想要另一个名为Row的类。Row将有一个名为Cells的向量,以便我可以将Cell和Cell类型的元素添加到该向量中。这是可能的吗?
如果是这样,我该如何做呢? 提前致谢。
根据您提供的详细信息,前两个答案都不可行。您需要的是一种称为单元格变量的类型,然后您可以拥有这些类型的向量。例如:
enum CellType
{
Int,
Float,
// etc
};
class Cell
{
CellType type;
union
{
int i;
float f;
// etc
};
};
class Vector
{
vector <Cell> cells;
};
class ICell
{
// list of cell methods
};
template <class T>
class Cell : public ICell
{
T data;
// implementation of cell methods
};
class Vector
{
vector <ICell *> cells;
};
这种方法可能更有效,因为你最初需要更新较少的代码来添加新的单元格类型,但是你必须在单元格向量中使用指针类型。如果你按值存储单元格 vector <ICell>
,那么由于对象切片,你将会丢失数据。
在C++中不可能实现以下操作,但在Java/Python中是可以的,原因是:在C++向量中,STL容器的存储(由vector::data()返回)按顺序打包了所有对象实例化。每个元素必须具有相同的大小,这使得寻址快速方便。因此,假设您定义了一个模板类A,
template <class T>
class A{
int id;
T obj;
};
它的大小将取决于模板变量"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));
}
记得编译时加上-std=c++11来启用C++11。
输出:
Deleting string1234
Deleting 1234
Deleting 1.234
您能得到您想要的! :)
在Java/Python中,每个类对象变量实际上是一个指针,因此,Java数组A或Python列表A等价于C++ A指针数组。因此,您可以获得基本相同的功能而无需显式创建shared_ptrs。
cpp:25:13: error: 'shared_ptr' was not declared in this scope
。 - Praveen Vinnytemplate<class T>
class Row
{
private:
class Cell {
string header;
T data;
}
std::vector<Cell> cells;
...
}
template<class T>
class Row
{
private:
std::vector<Cell<T> > cells;
};
好的,这个答案是不正确的。
所以,如果你想在一个 vector
中存储不同的单元格 - 你应该使用一些动态类型识别(你可以使用一个基类,在向量中存储指向它的指针,只使用虚函数,这些虚函数在所有派生类中被覆盖,你可以存储像boost::any
这样的东西,并为每个插入的元素保存一些类型标识
,以将它们转换为真实类型并与其一起工作)。
vector
是一个数组,因此其中所有元素应该具有相同的静态类型,但Cell<int>
和Cell<char>
是不相关的类型(不像Java中的泛型类)。 - Elazar
Cell<float>
和Cell<int>
放在一起。您需要使用指针和继承,并且必须知道自己在做什么。很容易创建一个无法使用的基类,而所有实质内容都在子类中,然后您就没有访问它的方法了。您需要在基类中放置实质内容。这意味着它必须具有可用的接口,不依赖于 T。 - n. m.