c++中不相关T的容器

container of unrelated T in c++

本文关键字:不相关 c++      更新时间:2023-10-16

如果我有以下假设类:

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有一个更好的方法来解决这个问题,boost::Any,但由于这是一个学习项目,我想自己做(我也很好奇找到一个很好的理由正确使用reinterpret_cast)。

如果您想要存储异构类型的对象,请考虑boost::anyboost::variant

在决定使用哪一个之前,看一下比较:

  • 提振。变体vs.增强。任何

希望它能帮助你做出正确的决定。从标准库中选择一个或任何容器来存储对象,std::stack<boost::any>std::stack<boost::variant>或任何其他容器。

我重复不要编写自己的容器。使用标准库中的容器。他们经过。

虽然可以转换为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,您可以让c++在运行时(使用RTTI)检查您的强制转换是安全的,只要被强制转换的类型(之前和之后)具有具有至少一个虚方法的公共基类型。

因此,首先用虚析构函数创建公共基类型:
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。

也就是说,异构容器几乎总是错误的;在某种程度上,你需要知道容器中有什么,这样你才能真正地使用它。通过创建这样的容器,您实际想要完成什么?

相关文章: