C++:模板类的向量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16210707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ : Vector of template class
提问by Jakir Hossain
I have a template class named Cell as follows:-
我有一个名为 Cell 的模板类,如下所示:-
template<class T>class Cell
{
string header, T data;
}
Now I want another class Named Row. Row will have a vector named Cells such that I can add both Cell and Cell type elements to that vector. Is it possible?
现在我想要另一个名为 Row 的类。Row 将有一个名为 Cells 的向量,这样我就可以将 Cell 和 Cell 类型元素添加到该向量中。是否可以?
If so, how can I do that? Thanks in advance.
如果是这样,我该怎么做?提前致谢。
回答by Skizz
With the extra detail you've provided, the first two answers won't work. What you require is a type known as a variant for the cell and then you can have a vector of those. For example:-
使用您提供的额外细节,前两个答案将不起作用。您需要的是一种称为细胞变体的类型,然后您可以拥有这些类型的向量。例如:-
enum CellType
{
Int,
Float,
// etc
};
class Cell
{
CellType type;
union
{
int i;
float f;
// etc
};
};
class Vector
{
vector <Cell> cells;
};
This, however, is a pain to add new types to as it requires a lot of code to maintain. An alternative could use the cell template with a common base class:-
然而,添加新类型很痛苦,因为它需要大量代码来维护。另一种方法可以使用具有公共基类的单元格模板:-
class ICell
{
// list of cell methods
};
template <class T>
class Cell : public ICell
{
T data;
// implementation of cell methods
};
class Vector
{
vector <ICell *> cells;
};
This might work better as you have less code initially to update to add a new cell type but you have to use a pointer type in the cells vector. If you stored the cell by value, vector <ICell>
, then you will lose data due to object slicing.
这可能会更好,因为您最初需要更新的代码较少以添加新的单元格类型,但您必须在单元格向量中使用指针类型。如果您按值存储单元格vector <ICell>
,那么您将因对象切片而丢失数据。
回答by xuancong84
The reason why this is NOT possiblein C++, but possible in Java/Python is because: in a C++ vector, the STL container's storage (returned by vector::data()) contains all the object instantiations sequencially packed. In which each element must have the same size. This makes addressing fast and convenient. Therefore, suppose you define a template class A,
之所以这是不可能在C ++中,但可能是Java / Python是因为:在C ++载体,在STL容器的存储(由矢量::数据()返回)包含了所有的对象实例sequencially包装。其中每个元素必须具有相同的大小。这使得寻址快捷方便。因此,假设您定义了一个模板类 A,
template <class T>
class A{
int id;
T obj;
};
Its size will depend on the template variable "T obj". Pushing the same class A of different template type T will make each element in the vector having different sizes, thus, this is impossible. The only way is to use vector of shared_ptr or unique_ptr of a base class. Both shared_ptr and unique_ptr are supported by C++11 and Boost. Each derived-class element can have different template types. In this way, when the base class pointer's destructor is called, the derived class's destructor will be invoked. For example,
它的大小将取决于模板变量“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));
}
Remember to compile with -std=c++11 to enable C++11.
请记住使用 -std=c++11 进行编译以启用 C++11。
Output:
输出:
Deleting string1234
Deleting 1234
Deleting 1.234
And you get what you want! :)
你得到你想要的!:)
In Java/Python, every class-object variable is actually a pointer, thus, a Java Array of A or a Python list of A is equivalent to a C++ array of pointers of A. Thus, you get essentially the same functionality without explicit creating shared_ptrs.
在 Java/Python 中,每个类对象变量实际上都是一个指针,因此,A 的 Java 数组或 A 的 Python 列表等价于 A 的 C++ 指针数组。因此,您无需显式创建即可获得基本相同的功能共享_ptr。
回答by ForEveR
Something like this?
像这样的东西?
template<class T>
class Row
{
private:
std::vector<Cell<T> > cells;
};
Okay, this answer is incorrect.
好吧,这个答案是错误的。
So, if you want to store in one vector
different cells - you should use some dynamic type identification (you can use one base-class and store pointer to it in vector, that use only virtual functions, that are overrided in all derived classes, you can store something like boost::any
and save some type-identification
for each inserted element, for cast them into real type and work with it).
因此,如果您想存储在一个vector
不同的单元格中 - 您应该使用一些动态类型标识(您可以使用一个基类并将指向它的指针存储在向量中,仅使用虚函数,在所有派生类中都被覆盖,您可以为每个插入的元素存储类似的内容boost::any
并保存一些type-identification
内容,以便将它们转换为真实类型并使用它)。
回答by Elazar
The other answer is good, but you probably wanted:
另一个答案很好,但您可能想要:
template<class T>
class Row
{
private:
class Cell {
string header;
T data;
}
std::vector<Cell> cells;
...
}