子类指针调用虚函数异常:第三次print()为何导致程序终止?
问题分析:dynamic_cast转换失败导致空指针解引用
先看你的代码:
#include <iostream> class A { public: virtual void print() { std::cout << "class A" << std::endl; } }; class B : public A { public: virtual void print() override { std::cout << "class B" << std::endl; } }; class C : public A { public: virtual void print() override { std::cout << "class C" << std::endl; } }; int main() { B obj1; A *ptr1 = dynamic_cast<A *>(&obj1); ptr1->print(); B *ptr2 = dynamic_cast<B *>(ptr1); ptr2->print(); C *ptr3 = dynamic_cast<C *>(ptr2); ptr3->print(); }
你遇到的前两次调用正常输出class B、第三次直接崩溃的核心原因是**dynamic_cast跨类型转换失败返回空指针,后续解引用空指针触发了未定义行为**:
- 第一次转换:
B*转A*是向上转型,属于安全的隐式转换(这里用dynamic_cast只是多此一举,但肯定成功),ptr1指向obj1,调用虚函数时会根据对象实际类型(B)匹配对应的print,输出class B。 - 第二次转换:
A*转B*是向下转型,因为ptr1实际指向的是B类型对象,dynamic_cast会成功,ptr2同样指向obj1,调用print还是输出class B。 - 第三次转换:
B*转C*,B和C都是A的子类,但彼此之间没有继承关系,dynamic_cast无法完成这种跨类型转换,会返回nullptr(空指针)。此时直接用ptr3->print(),相当于对空指针调用成员函数——空指针没有指向任何有效对象,找不到对应虚表,程序会直接崩溃(通常表现为段错误)。
如果要避免这类问题,每次用dynamic_cast后都应该先检查指针是否为空:
C *ptr3 = dynamic_cast<C *>(ptr2); if (ptr3 != nullptr) { ptr3->print(); } else { std::cout << "转换失败,ptr3是空指针" << std::endl; }
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

