如何创建一个包含任何类型指针的容器

时间:2014-07-05 01:06:15

标签: c++ pointers

这看起来很愚蠢,但我想创建一个容纳任何类型指针的容器,这样我就可以将每个指针存储在那里,然后轻松删除它们。我试过了:

vector<void*> v;

v.push_back(new Dog());
v.push_back(new Cat());

cout <<  v[0]; // prints mem address
cout <<  v[1]; // prints another mem address
cout << *v[0]; // compiler yells at me

但显然你无法取消引用void指针。有没有办法制作任何类型的指针的通用容器,而不必让每个类都扩展一个名为“Object”的超类或什么?

4 个答案:

答案 0 :(得分:2)

您可以实现指针包装器一个模板类,该类继承自公共基类并将其放置到容器中。一些事情:

class pointer_wrapper_base
{
public:
  virtual void delete_pointee()=0;
protected:
  void *m_ptr;
};

template<class T>
class pointer_wrapper: public pointer_wrapper_base
{
public:
  pointer_wrapper(T *ptr_) {m_ptr=ptr_;}
  virtual void delete_pointee()
  {
    delete (T*)m_ptr;
  }
};

一旦有了这个类,就可以使用poly-variant类,就像变体类一样,但是所有不同的变体都有共同的基类。如果你想看一下,我在这里有一个实现:http://sourceforge.net/p/spinxengine/code/HEAD/tree/sxp_src/core/utils.h(搜索poly_pod_variant):

  std::vector<poly_pod_variant<pointer_wrapper_base> > x;
  x.push_back(pointer_wrapper<Cat>(new(Cat)));
  x[0]->delete_pointee();

或者如果您对包装器的动态分配没问题,那么您当然可以将指向pointer_wrap_base的指针存储到向量中,例如

std::vector<std::unique_ptr<pointer_wrapper_base> > x;
x.push_back(std::unique_ptr<pointer_wrapper_base>(new(pointer_wrapper<Cat>)(new Cat)));
x[0]->delete_pointee();

答案 1 :(得分:1)

考虑使用Boost的一些类,例如boost :: any,http://www.boost.org/doc/libs/1_55_0/doc/html/any.html及其示例代码,http://www.boost.org/doc/libs/1_55_0/doc/html/any/s02.html

或者,也可以看看Boost的变体。

一般来说,学习Boost。它会让你感到震惊,并且还会为你的C ++开发提供动力。

答案 2 :(得分:1)

C ++有一个静态类型系统。这意味着必须在编译时知道所有表达式的类型。您的问题的解决方案取决于您将如何处理对象。

选项1:让CatDog派生自一个班级

如果所有对象都有一个公共接口,并且你可以让它们从一个类派生,那么这是有意义的。

std::vector<std::unique_ptr<Animal>> vec; // good practice - automatically manage 
                                          // dynamically allocated elements with
                                          // std::unique_ptr

vec.push_back(std::make_unique<Dog>()); // or vec.emplace_back(new Dog());
vec.push_back(std::make_unique<Cat>()); // or vec.emplace_back(new Cat());

std::cout << *v[0];

选项2:boost::any

如果类型不相关,这是有意义的。例如,您存储类的int和对象。显然你无法从你的班级中获得int。因此,您使用boost::any进行存储,然后将其强制转换为对象的类型。如果转换为不相关的类型,则抛出类型boost::bad_any_cast的异常。

std::vector<boost::any> vec;
vec.push_back(Dog());
vec.push_back(25);

std::cout << boost::any_cast<int>(vec[1]);

另外,指针。 “我想要正确管理我的内存”的解决方案是“不要使用new delete”这些是帮助您执行此操作的工具,无需特别顺序:

  • std::string而不是以null结尾的字符串
  • std::vector<T>代替new T[]
  • std::unique_ptr<T>而不是指向多态对象的原始指针
  • ...或std::shared_ptr<T>如果您分享

答案 3 :(得分:0)

cout&lt;&lt; *((Dog *)v [0]);

我假设你的Dog类是可串行的,否则你会得到一种不同的错误,但你的类型转换问题应该通过(Dog *)类型转换来解决。