You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类指针调用虚函数异常:第三次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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:00:06