将 void* 投射到更高的东西的安全方法?
我有一个通用类来管理各种类型的资源,但由于我不想为每个 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* 指针可以是任何东西),我想至少在运行时检查转换是否有效,这样我就可以在不导致应用程序崩溃的情况下对其做出反应。
我该怎么做?
I've got a generic class that manages resources of all kinds of types, but since I don't want to create an instance of ResourceManager for every T there is (thus having one resource manager for each type T), I have to make the type of T unknown to the ResourceManager class.
I do this by saving a map of void* pointers and converting them back to the required format if someone requests a certain type out of a templated Load() method;
template <typename T>
T* Load(const std::string &location)
{
//do some stuff here
//everybody take cover!!!
return static_cast<T*>(m_resources[location]);
}
I use template specialization to introduce different Loaders to the class:
template<>
AwesomeType* Load(const std::string &location)
{
//etc.
return static_cast<AwesomeType*>(m_resources[location]);
}
I am aware that this is ugly, but there is no way around it right now. I could introduce static maps in the inside of the specialized Load methods, but that way I can't bind the lifetime of the resources to the lifetime of an ResourceManager object, which is an essential feature.
But since this is somewhat dangerous (since those void* pointers can be anything), I'd like to at least check at runtime if the conversion is going to work, so I can react to it without having the application crash.
How can I do this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
除非您存储指示每个指针实际类型的附加信息,否则无法检查您可以将
void*
转换为什么。一种更“C++ 方式”来完成您想要的操作,是从抽象基类
Resource
派生每个资源类,并将指向Resource
的指针映射存储在资源管理器中。然后你可以使用dynamic_cast
转换为所需的类型,如果指针指向错误类型的对象,这将返回NULL
。或者(取决于您想要做什么)您可以简单地返回一个Resource*
指针并使用虚函数来实现每个资源的功能。There is no way to check what you can cast
void*
to, unless you store additional information that indicates the actual type with each pointer.A more "C++ way" to do what you want is to derive each resource class from an abstract base class
Resource
, and store a map of pointers toResource
in your resource manager. Then you can usedynamic_cast<T*>
to convert to the required type, and this will returnNULL
if the pointer is to an object of the wrong type. Or (depending on what you want to do) you can simply return aResource*
pointer and use virtual functions to implement the functionality of each resource.如果您扩展保存的值类型,则可以轻松地做到这一点 - 使其成为一个还保存
type_info
对象的结构:这与我的做法类似,但我使用
shared_ptr
void>
以节省资源。You can easily do this, if you extend your saved value type - make it a struct that also saves a
type_info
object:This is similar to how I do it, but I use a
shared_ptr<void>
to save the resources.(我确信有关 void 指针的许多其他问题已经回答了这个问题,但我们开始......)
你无法检查。这就是 void* 指针的问题。您不知道它们指向什么,并且您不能(不允许)在不知道其类型的情况下检查它们指向的内存。
如果你有一个
void*
,你必须事先知道它真正指向的是什么,然后进行适当的转换。(I'm sure this is already answered by many other questions about void pointers, but here we go ...)
You cannot check. This is the thing about void* pointers. You don't have a clue what they are pointing to, and you cannot (are not allowed to) inspect the memory they point to without knowing its type.
If you have a
void*
you simply must know beforehand what it is really pointing to and then cast appropriately.