关于void*转换后dynamic_cast跨派生类转换的有效性疑问
关于void*转换后dynamic_cast跨派生类转换的有效性疑问
嘿,这个问题问得很实际啊,我来给你讲明白~
首先先明确你的场景:你有这么一套继承关系:
class Base { // ... }; class Derived : public Base { // ... }; class OtherDerived : public Base { // ... };
并且你能100%确定voidPtr要么是nullptr,要么指向Derived或者OtherDerived的对象。现在你在函数里这么写:
void someFunction(void* voidPtr) { auto derived = dynamic_cast<Derived*>(static_cast<Base*>(voidPtr)); if (derived == nullptr) { return; } // do something with derived }
你担心的是:如果voidPtr实际指向的是OtherDerived对象,会不会dynamic_cast返回非空指针,导致后面错误操作?
答案是:完全不会,这种情况下dynamic_cast一定会返回nullptr,你的代码逻辑是安全的。
为啥呢?我给你拆解两步来看:
- 第一步的
static_cast<Base*>(voidPtr):因为你确定voidPtr指向的是Base的公有派生类对象,这个转换是合法的,它会把指针调整到对象的Base子对象的地址上(公有继承的情况下,基类指针和派生类指针的地址通常是一致的,但这不是重点,重点是这个转换是安全的,能得到有效的Base*)。 - 第二步的
dynamic_cast<Derived*>(...):dynamic_cast的核心作用就是做运行时类型检查,它会根据Base*指向的实际对象类型来判断能不能转换成Derived*。如果实际对象是OtherDerived,那它和Derived是平级的派生类,没有继承关系,所以dynamic_cast会直接返回nullptr,不会给你一个无效的指针。
补充个小细节:这个检查依赖于编译器开启了RTTI(运行时类型信息),不过一般主流编译器默认都是开启的,除非你手动关闭了这个选项——如果真关了,那dynamic_cast的行为就不确定了,但正常开发场景下不用操心这个。
回到你Qt的使用场景:用QVariant::data()拿到void*的情况,只要你能确定这个void*的实际类型范围(就像你说的要么是Derived要么是OtherDerived),这个写法是完全可靠的,不用担心误判的问题。
备注:内容来源于stack exchange,提问作者Jaakko
相关产品推荐
相关产品推荐

