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

关于虚拟继承程序输出结果的困惑

嘿,我来帮你拆解这段虚拟继承代码的输出逻辑,先给你看程序实际运行的输出结果,再一步步讲清楚原因:

e.A::m = 5005
e.D::m = 6006
e.m = 303
先理清你的继承结构

先把继承链梳理清楚,这是理解问题的基础:

  • A 是最顶层基类,自带成员 m = 5005
  • B 普通继承(非虚拟)自 A
  • C 虚拟继承自 B
  • D 虚拟继承自 B,同时自己额外定义了成员 m = 6006
  • E 多继承自 C 和 D

这里的关键是:C 和 D 都用了虚拟继承 B,所以在 E 的对象中,只会存在一个 B 的实例——这正是虚拟继承的核心作用,用来解决多继承中“菱形继承”导致的基类实例重复问题。

逐个分析输出内容

1. e.A::m = 5005

B 是普通继承 A,所以那个唯一的 B 实例里包含了一个 A 的实例,A::m 的初始值就是5005。你通过e.A::m明确指定了要访问 A 类的成员,所以直接取到这个初始值,完全不受其他类中同名m的影响。

2. e.D::m = 6006

D 类自己定义了成员 m,这个m和A里的m是完全独立的两个成员(只是名字相同而已)。e.D::m明确指定访问D类的m,所以取到的是D中初始化的6006——哪怕你后面给e.m赋值了303,也不会改变D子对象里的这个m值,因为你赋值的是E对象最终解析的m,不是D内部的存储值。

3. e.m = 303

这是最容易困惑的点,当你直接写e.m时,编译器会遵循名字查找优先级来确定访问哪个m:

  • C 继承自B,B又继承自A,所以C的作用域里能看到A::m,但C自己没定义新的m
  • D 自己定义了m,根据C++的名字隐藏规则,这个m会把从B继承来的A::m给隐藏掉
  • E 同时继承C和D,此时C带来的A::m和D带来的D::m中,编译器会优先选择自身定义了成员的基类版本(也就是D::m),因为它的优先级更高(自己定义的比继承来的更“具体”)

所以e.m实际上绑定的是D类的m成员,你给它赋值303后,输出自然就是303了。

额外小补充

如果想直接访问A::m而不写A::限定符,你可以用e.B::m或者e.C::m,因为B和C都继承了A的m,而且没有自己定义同名成员,所以它们的m就是A::m。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:48:01