容器中的无关T在c ++ [英] container of unrelated T in c++

查看:121
本文介绍了容器中的无关T在c ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有以下假设的类:

 命名空间系统
{
template< class T>
class Container
{
public:
Container(){}
〜Container(){}
}
}

如果我实例化两个不同T的容器,比如:

  Container< int>一个; 
Container< string> b;

我想创建一个指向a和b的向量。由于a和b是不同类型,通常这是不可能的。然而,如果我做了像:

  std :: stack< void *> _采集; 
void * p = reinterpret_cast< void *>(& a);
void * q = reinterpret_cast< void *>(& b);
_collection.push(a);
_collection.push(b);

稍后,我可以从_collection中取回a和b,如下所示:

 容器< string> b = * reinterpret_cast< Container< string> *>(_ collection.pop()); 
Container< int> a = * reinterpret_cast< Container< int> *>(_ collection.pop());我的问题是,这是存储一组无关类型的最好方法吗?这也是从向量(重新解释转换)存储和检索指针的首选方式?我已经看过周围,看到boost有一个更好的方法来解决这个问题,Boost :: Any,但因为这是一个学习项目,我在我想自己做(我也很想找到一个很好的理由正确使用reinterpret_cast。)

解决方案

虽然可以转换为 void * 回来,问题是知道你弹出哪种类型。毕竟,您给出了示例:

 容器< string> b = * reinterpret_cast< Container< string> *>(_ collection.pop()); 
Container< int> a = * reinterpret_cast< Container< int> *>(_ collect.pop());

但是,如果你不小心做了:

 容器< int> a = * reinterpret_cast< Container< int> *>(_ collection.pop()); 
Container< string> b = * reinterpret_cast< Container< string> *>(_ collection.pop());

现在你有指向错误类型的指针,可能会看到崩溃 - / p>

如果您想这样做,至少使用 dynamic_cast 你有正确的类型。使用 dynamic_cast ,您可以在运行时使用C ++检查(使用 RTTI ),只要正在投放的类型(前后都有)具有至少包含一个虚拟方法的公共基本类型,您的转换就是安全的。



因此,首先使用虚拟析构函数创建一个公共基类型:

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

使容器从中衍生出来:

  template< typename T> 
类容器:public ContainerBase {
// ...
}

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



也就是说,异构容器几乎总是错误的使用;在某种程度上,你需要知道容器中的什么,所以你可以实际使用 。你真正想通过创建一个这样的容器来实现什么?


If I have the following hypothetical class:

namespace System
{
    template <class T>
    class Container
    {
    public:
        Container() { }
        ~Container() { }
    }
}

If I instantiate two Containers with different T's, say:

Container<int> a;
Container<string> b;

I would like to create vector with pointers to a and b. Since a and b are different types, normally this wouldn't be possible. However, if I did something like:

std::stack<void*> _collection;
void *p = reinterpret_cast<void*>(&a);
void *q = reinterpret_cast<void*>(&b);
_collection.push(a);
_collection.push(b);

Then later on, I can get a and b back from _collection like so:

Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());

My question is, is this the best way for storing a collection of unrelated types? Also would this be the preferred way of storing and retrieving the pointers from the vector (the reinterpret cast)? I've looked around and seen that boost has a nicer way of solving this, Boost::Any, but since this is a learning project I am on I would like to do it myself (Also I have been curious to find a good reason to use a reinterpret_cast correctly).

解决方案

While it is possible to cast to void * and back, the problem is knowing which type you're popping. After all, you give the example:

Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());

However, if you were to accidentally do:

Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());

Now you've got pointers to the wrong type, and will likely see crashes - or worse.

If you want to do something like this, at least use dynamic_cast to check that you have the right types. With dynamic_cast, you can have C++ check, at runtime (using RTTI), that your cast is safe, as long as the types being casted (both before and after) have a common base type with at least one virtual method.

So, first create a common base type with a virtual destructor:

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

Make your containers derive from it:

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

Now use a std::stack<ContainerBase *>. When you retrieve items from the stack, use dynamic_cast<Container<int> >(stack.pop()) or dynamic_cast<Container<string> >(stack.pop()); if you have the types wrong, these will check, and will return NULL.

That said, heterogeneous containers are almost always the wrong thing to be using; at some level you need to know what's in the container so you can actually use it. What are you actually trying to accomplish by creating a container like this?

这篇关于容器中的无关T在c ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆