【问题标题】:container of unrelated T in c++C ++中不相关T的容器
【发布时间】:2011-08-22 16:23:52
【问题描述】:

如果我有以下假设类:

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)。

【问题讨论】:

标签: c++ generics containers


【解决方案1】:

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

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

希望它能帮助您做出正确的决定。从标准库中选择一个和任何容器来存储对象,std::stack&lt;boost::any&gt;std::stack&lt;boost::variant&gt; 或任何其他容器。 不要编写自己的容器。

我再说一遍不要编写自己的容器。使用标准库中的容器。它们经过充分测试。

【讨论】:

  • 您是否有预先制定的标准答案集,或者您是如何做到这么快的? :)
  • @pmr: 这样的问题被问了太多次了:stackoverflow.com/questions/7132248/union-vs-static-castvoid/…
  • 我知道。但我仍然尝试输入我自己的答案。为什么不直接投票结束这个?
  • @pmr:我怀疑它是否完全重复,但如果他对语言足够了解,那么他可以从其他主题中得到答案。但从他的帖子来看,他似乎只是一个新手,正在尝试探索该语言,编写自己的异构类型对象容器。所以让他从不同的人那里得到更多不同的回应。
【解决方案2】:

虽然可以转换为 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++ 检查您的转换是安全的,只要被转换的类型(之前和之后)具有至少一个虚拟方法的公共基类型.

所以,首先创建一个带有虚拟析构函数的通用基类型:

class ContainerBase {
public:
  virtual ~ContainerBase() { }
};

让你的容器派生自它:

template <typename T>
class Container : public ContainerBase {
// ...
}

现在使用std::stack&lt;ContainerBase *&gt;。从堆栈中检索项目时,使用dynamic_cast&lt;Container&lt;int&gt; &gt;(stack.pop())dynamic_cast&lt;Container&lt;string&gt; &gt;(stack.pop());如果你的类型错误,这些将检查,并返回 NULL。

也就是说,异构容器几乎总是不适合使用;在某种程度上,您需要知道容器中的内容,以便您可以真正使用它。通过创建这样的容器,您实际上想要完成什么?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 2021-02-01
    • 1970-01-01
    相关资源
    最近更新 更多