这看起来很愚蠢,但我想创建一个容纳任何类型指针的容器,这样我就可以将每个指针存储在那里,然后轻松删除它们。我试过了:
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”的超类或什么?
答案 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:让Cat
和Dog
派生自一个班级
如果所有对象都有一个公共接口,并且你可以让它们从一个类派生,那么这是有意义的。
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 *)类型转换来解决。