将父类reinterpret_cast为子类后,父类函数能否调用子类函数?
问题解答
首先必须明确:你用reinterpret_cast<B*>(ab)把实际类型为A的对象指针强转为B*,这属于C++标准定义的未定义行为——也就是说,这么做之后任何操作的结果都是不可预测的,编译器和运行环境没有义务保证代码按你预期工作,本质上是错误的写法。
当前调用bab->func1()输出class A的原因很简单:func2是虚函数,虚函数的调用基于对象实际的虚表。你创建的对象是A类型,它的虚表中func2对应的就是A::func2,不管你把指针转成什么类型,虚函数调用都会指向实际对象的虚表条目,所以还是会执行A::func2。
关于你要的“无需重定义func1”的实现方式
不存在标准、安全且可移植的方法能实现这个需求,因为你的核心操作(把A对象当成B对象用)本身就违反了C++的类型系统规则。
如果非要强行达到这个效果(强烈不推荐,仅作为技术探讨),可以尝试手动修改对象的虚表指针,但这完全依赖编译器的虚表实现(比如GCC/Clang和MSVC的虚表结构就不一样),而且会带来严重的内存安全问题和移植性问题。示例代码(仅适用于GCC/Clang,无任何安全性保证):
#include <iostream> class A { public: void func1() { func2(); } protected: virtual void func2() { printf("class A\n"); } }; class B : public A { protected: virtual void func2() { printf("class B\n"); } }; // 获取类的虚表地址(仅GCC/Clang有效) template<typename T> void** get_vtable(T* obj) { return *reinterpret_cast<void***>(obj); } int main() { A* ab = new A(); ab->func1(); // 输出class A B temp_b; void** b_vtable = get_vtable(&temp_b); // 修改A对象的虚表指针为B的虚表 *reinterpret_cast<void***>(ab) = b_vtable; B* bab = reinterpret_cast<B*>(ab); bab->func1(); // 此时会输出class B,但属于未定义行为 delete ab; return 0; }
正确的做法
如果你需要调用B::func2,应该直接创建B类型的对象,利用C++正常的多态机制:
int main() { A* ab = new B(); // 父类指针指向子类对象 ab->func1(); // 自动输出class B,无需重定义func1 delete ab; return 0; }
这才是符合C++类型系统和多态设计的正确写法,安全且可移植。
内容的提问来源于stack exchange,提问作者Bonic
相关产品推荐
相关产品推荐

