虚基类指针强制类型转换成派生类指针 伴随的一些问题,望高人解答
由于一些原因,本人的程序中需要将虚基类指针强制类型转换成派生类指针
大家应该知道,这是被C++禁止的,如下写法,编译器就会报错:
- C/C++ code
class BaseClass {};class DerivedClass : public virtual BaseClass { void A(); };DerivedClass test;BaseClass * pB = &test;DerivedClass * pD = (DerivedClass *)pB; // C2635错误
我尝试用void *骗过编译器,虽然没有了编译错误,但是当我使用 pD调用一个DerivedClass的函数时,会得到一个运行错误:
- C/C++ code
DerivedClass * pD = (DerivedClass *)(void *)pB; // 编译无错pD->A(); // 调用函数会有运行时错误
当我打开C++的RTTI并将上述语句修改成如下样子之后,就一切正常了。
- C/C++ code
DerivedClass * pD = dynamic_cast<DerivedClass *>pB;pD->A();
哪个高人能够给我解释一下:
1、为什么C++禁止这样的类型转换?
2、为什么我用void *欺骗编译器后,用pD调用一个函数会产生一个运行时错误?
3、为什么dynamic_cast能解决这些问题?
[解决办法]
1.c++ 没有禁止虚基类到派生类的转换,不过 c++ 要求这样的转换必须经由 dynamic_cast 完成。(DerivedClass *)pB 写法的叫做 explicit type conversion (cast notation),标准规定 cast notation 不能执行 dynamic_cast 的功能,所以此处的用法是错误的。
2.因为这样的类型转换导致 undefined behavior,标准不对这样的行为做任何规范,编译无误,运行崩溃是可以接受的 UB。从实践的角度讲,VS 系列的编译器倾向于将虚基类子对象放在 most derived object 的尾端,因此 pB 和 pD 指向的地址不一样,强行通过 void* 过度导致必要的调整缺失,再调用成员函数就会出错了。
3.因为 dynamic_cast 专门干这项工作的,标准对其行为有清晰的界定。
[解决办法]
“基类指针强制类型转换成派生类指针” 这种需求合理吗?