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

C++桥接模式运行触发纯虚函数调用错误的原因咨询

崩溃根源:悬空引用

你碰到的pure virtual method called报错和桥接模式的逻辑无关,本质是引用悬空导致的未定义行为:

  • 初始化shapes向量时,传入CircleShape构造器的DrawingAPI01{}、DrawingAPI02{}都是临时匿名对象,没有独立的持久生命周期。
  • Shape类用const DrawingAPI& drawing_api_存储传入的引用,只是把引用绑定到了上述临时对象上。C++规则里,const左值引用能延长临时对象生命周期的效果,仅在直接绑定的当场语句内生效,只要把引用存到类的成员变量里,这种延长就完全失效——整行向量初始化执行完,两个临时的DrawingAPI子类实例会立刻被析构。
  • 后续循环调用drawing_api_.DrawCircle()时,持有的引用已经指向已回收的内存。对象析构过程中,虚表指针会从子类逐步回退到基类的虚表项,等对象完全销毁后,虚表就指向了包含纯虚函数地址的基类表,这时候调用方法自然会触发纯虚函数的运行时报错。
  • 编译器全程没报错,是因为把临时对象绑定到const左值引用本身是合法语法,这种跨语句的生命周期不匹配属于运行时未定义行为,普通静态编译不会做这类检查。
修复方向

按照桥接模式“抽象层持有实现层生命周期控制权”的设计本意,推荐两类改法:

  • 优先方案:用智能指针接管实现对象的所有权
    把Shape类里的drawing_api_从常量引用换成std::unique_ptr<DrawingAPI> drawing_api_,构造函数直接接收实例化的DrawingAPI子类实例的所有权,由Shape类负责实现对象的析构,从根本上避免临时对象提前销毁的问题。这种写法完全符合桥接模式“抽象和实现解耦、独立变化”的设计目标。
  • 临时规避方案(不推荐复用)
    在main函数里提前定义带持久生命周期的命名DrawingAPI01、DrawingAPI02变量,再把这些变量的引用传给CircleShape的构造函数,保证引用绑定的对象存活周期覆盖所有Shape的使用阶段。这种写法没有解决类成员不持有对象所有权的核心隐患,后续调整代码结构时很容易再次触发悬空引用问题。

注意:很多开发者对const引用的生命周期延长规则存在误解,以为只要用const引用接住临时对象,临时对象就会和引用同生共死。实际上这种延长只覆盖最外层的绑定语句,一旦把引用存到类成员中,临时对象的析构时机完全不受引用控制,是C++里非常常见的踩坑点。

内容的提问来源于stack exchange,提问作者k0ala Xing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 10:27:03