c ++中无关T的容器

时间:2011-08-22 16:23:53

标签: c++ generics containers

如果我有以下假设课程:

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。

2 个答案:

答案 0 :(得分:6)

如果要存储异类型的对象,请考虑boost::anyboost::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。

也就是说,异构容器几乎总是使用错误的东西;在某种程度上,您需要知道容器中的内容,以便您实际上使用它。您通过创建这样的容器实际上想要实现什么目标?