如何创建一个可以容纳任意类型指针的容器?
How do I make a container that holds pointers of any type
这可能看起来很傻,但我想创建一个容器来保存任何类型的指针,这样我就可以将每个指针存储在那里,然后很容易地删除它们。我试着:
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指针。有没有一种方法可以使任何类型的指针的泛型容器,而不必使每个类扩展一个超类称为"对象"或什么?
你可以实现一个模板类的指针包装器,该模板类继承了一个通用的基类,并将其放置到容器中。下面的内容:
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;
}
};
一旦你有了这个类,你就可以使用多变体类,例如,它就像变体类,但是所有不同的变体都有一个共同的基类。我有一个实现在这里,如果你想看看: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();
研究一下使用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++有一个静态类型系统。这意味着在编译时必须知道所有表达式的类型。问题的解决方案取决于你打算如何处理这些对象。
选项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
s和类的对象。显然,你不能使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
代替以空结尾的字符串 -
std::vector<T>
代替new T[]
-
std::unique_ptr<T>
代替原始指针指向多态对象 - …或
std::shared_ptr<T>
,如果你分享它们
count <*((狗*)v[0]);
我在这里假设你的Dog类是可字符串化的,否则你会得到不同类型的错误,但是你的类型转换问题应该通过(Dog *)类型强制转换来解决。
- 从函数返回任意简单类型的数据
- C++ - 声明指向返回任何类型并获取任意数量参数的函数的指针
- 类型别名允许分配任意指针,尽管 int* 是必需的
- 包装任意类型/非类型模板类的模板类
- 使用模板将任意类型参数传递给 C++ 中的函数
- 有没有办法找到任意类类型的直接基类(如果有的话)?
- is_invocable使用任意函数参数类型
- 如何动态执行具有任意参数类型的函数指针
- 创建一个模板函数来读取 hdf5 中的任意数据类型
- 如何根据特定类型任意启用或禁用类方法
- C++任意整数(基本类型)的随机数
- C++11 中任意类型 T 的最小值/最大值
- C/C++对一块内存进行malloc,然后对不同的任意类型使用不同的部分
- 将任意数量的任意类型的值组合为单个字符串的简单命令
- 递归类型真的是构建不连续的任意大小数据结构的唯一方法吗
- 在一组模板参数中插入任意数量的类型
- protobuf 3中的基元类型任意
- C++类中的任意数据类型
- 如何在任意依赖类型上专门化模板
- 指向任意类方法的模板非类型指针