将void*转换为更高的东西的安全方法
Safe way of casting void* to something higher?
我有一个管理各种类型资源的泛型类,但由于我不想为每个T创建ResourceManager的实例(因此每种类型T都有一个资源管理器),因此我必须使ResourceManager类不知道T的类型。
我通过保存void*指针的映射并将它们转换回所需的格式来实现这一点,如果有人从模板化的Load()方法中请求某种类型;
template <typename T>
T* Load(const std::string &location)
{
//do some stuff here
//everybody take cover!!!
return static_cast<T*>(m_resources[location]);
}
我使用模板特化来为类引入不同的加载器:
template<>
AwesomeType* Load(const std::string &location)
{
//etc.
return static_cast<AwesomeType*>(m_resources[location]);
}
我知道这很难看,但现在没有办法。我可以在专门的Load方法内部引入静态映射,但这样我就不能将资源的生命周期绑定到ResourceManager对象的生命周期,而这是一个基本特性。
但是因为这有点危险(因为那些void*指针可以是任何东西),我想至少在运行时检查转换是否会工作,所以我可以对它做出反应,而不会导致应用程序崩溃。
我该怎么做?
没有办法检查您可以将void*
转换为什么,除非您存储额外的信息,这些信息表明每个指针的实际类型。
一个更"c++的方式"去做你想做的是从一个抽象基类Resource
派生每个资源类,并在你的资源管理器中存储一个指向Resource
的指针映射。然后,您可以使用dynamic_cast<T*>
转换为所需的类型,如果指针指向错误类型的对象,这将返回NULL
。或者(取决于你想做什么)你可以简单地返回一个Resource*
指针并使用虚函数来实现每个资源的功能。
您可以很容易地做到这一点,如果您扩展您保存的值类型-使其成为一个结构体,也保存type_info
对象:
#include <type_info>
struct ResourceInfo
{
std::type_info const& info;
void* ptr;
};
// ...
// just to give you the general idea
template<class Res>
void CacheResource(std::string const& location, Res* res)
{
ResourceInfo ri = { typeid(Res), res };
m_resources.insert(std::make_pair(location, ri));
}
template<class Res>
Res* Load(std::string const& location)
{
map_type::const_iterator res_it = m_resources.find(location);
if(res_it != m_resources.end())
{
if(typeid(Res) != res_it->second.info)
{
throw SorryBuddyWrongResourceType(some_info_here);
}
return static_cast<Res*>(res_it->second.ptr);
}
}
这与我的做法相似,但我使用shared_ptr<void>
来节省资源。
(我相信这已经回答了许多其他关于void指针的问题,但我们继续…)
但是因为这有点危险(因为那些void*指针可以任何东西),我想至少检查一下在运行时,如果转换正在进行这样我就能对它做出反应导致应用程序崩溃
不能检查。这就是void*指针的特点。你不知道它们指向的是什么,在不知道它们指向的内存类型的情况下,你不能(也不允许)检查它们指向的内存。
如果你有一个void*
,你必须事先知道它真正指向什么,然后适当地强制转换。
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 在 c++ 中从执行的 shell 命令获取返回状态的安全方法是什么?
- 在C++线程内实现多个计时器的最安全方法
- 最有效的安全方法将 std::map<int, std::shared_ptr> 转换为 std::<Base>map<int, std::shared_ptr<D
- 重新分配指针阵列的一部分的安全方法
- 将整数添加到数组值而无需调用它的最安全方法
- 使用括号运算符实现矩阵类的安全方法
- 将空隙动态铸造到类型的安全方法?
- C/通过套接字发送time_t的最安全方法
- 交换两个类实例的最安全方法
- 将uint16_t投射到wchar_t的安全方法
- 从字符串中读取溢出双倍作为'inf'的安全方法
- 期货是检查单个线程完成情况的安全方法吗
- 在C++中动态分配向量的安全方法是什么
- 在C++类中构建互斥保护的线程安全方法
- C++和跳出动态生成代码的安全方法
- 这是实现错误处理的安全方法吗
- 将长整数转换为字符数组的最安全方法是什么
- 缓存 PID 到端口映射窗口的安全方法
- 将无符号长整整除以无符号长整型的最安全方法