如果我有以下假设课程:
namespace System
{
template <class T>
class Container
{
public:
Container() { }
~Container() { }
}
}
如果我实例化两个具有不同T的容器,请说:
Container<int> a;
Container<string> b;
我想用指向a和b的指针创建向量。由于a和b是不同的类型,通常这是不可能的。但是,如果我做了类似的事情:
std::stack<void*> _collection;
void *p = reinterpret_cast<void*>(&a);
void *q = reinterpret_cast<void*>(&b);
_collection.push(a);
_collection.push(b);
然后,我可以像这样从_collection中获得a和b:
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
我的问题是,这是存储不相关类型集合的最佳方式吗?这也是存储和检索向量指针(重新解释转换)的首选方法吗?我环顾四周,看到提升有一个更好的解决方法,Boost :: Any,但由于这是一个学习项目,我想自己做(我也很好奇找到一个很好的理由正确使用reinterpret_cast。
答案 0 :(得分:6)
如果要存储异类型的对象,请考虑boost::any
或boost::variant
。
在决定使用哪一个之前,先看一下比较:
希望它能帮助您做出正确的决定。从标准库中选择一个容器和任何容器来存储对象std::stack<boost::any>
,std::stack<boost::variant>
或任何其他容器。 不要自己编写容器。
我重复不要写自己的容器。使用标准库中的容器。他们经过了充分的考验。
答案 1 :(得分:4)
虽然可以转换为void *
并返回,但问题在于知道您正在弹出哪种类型。毕竟,你举个例子:
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
但是,如果你不小心做了:
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
现在你有错误类型的指针,可能会看到崩溃 - 或者更糟。
如果你想做这样的事情,至少使用dynamic_cast
检查你是否有正确的类型。使用dynamic_cast
,您可以在运行时(使用RTTI)进行C ++检查,只要输出的类型(前后都有)具有at的公共基类型,至少一种虚拟方法。
因此,首先使用虚拟析构函数创建公共基类型:
class ContainerBase {
public:
virtual ~ContainerBase() { }
};
让您的容器从中派生出来:
template <typename T>
class Container : public ContainerBase {
// ...
}
现在使用std::stack<ContainerBase *>
。从堆栈中检索项目时,请使用dynamic_cast<Container<int> >(stack.pop())
或dynamic_cast<Container<string> >(stack.pop())
;如果你的类型错了,这些将检查,并将返回NULL。
也就是说,异构容器几乎总是使用错误的东西;在某种程度上,您需要知道容器中的内容,以便您实际上使用它。您通过创建这样的容器实际上想要实现什么目标?