remix编译运行solidity5
Solidity 继承与 override 教学示例,涉及 virtual、override 和多继承的菱形问题。
TokenV1.sol
1 | |

virtual:表示这个函数可以被, 子合约 重写(override)。
pure:不访问链上状态。
TokenV2.sol
1 | |
解释:
override:表示这个函数是 重写父类的 virtual 函数。
现在调用 TokenV2.version() 返回 “v2”,而 TokenV1.version() 仍返回 “v1”。
多继承的菱形问题是什么?
非常好的问题 👏
这是 Solidity 初学者在理解“继承”时最重要的难点之一。
我们一步步拆开讲清楚——
什么是「多继承的菱形问题(Diamond Inheritance Problem)」、
为什么会出错、
Solidity 是如何解决的。
🧩 一、菱形继承是什么
假设我们有四个合约:
1 | |
这就是所谓的「菱形继承结构」。
- 合约
A是最顶层父类 - 合约
B、C都继承了A - 合约
D同时继承B和C
于是问题来了 ——D 到底该继承 A 的版本 还是 B、C 的版本?
💣 二、冲突示例
1 | |
⚙️ 三、问题原因
Solidity 不知道 D.say() 应该继承自哪个父类:
- 从
B继承得到的say()返回"B" - 从
C继承得到的say()返回"C"
它们都源自 A,形成一条菱形路径:
1 | |
如果没有显式指定,编译器会报错:
1 | |
🧠 四、Solidity 如何解决
通过两个规则:
强制显式 override
你必须写override(B, C)明确告诉编译器你要覆盖这两个父类。线性化继承(C3 Linearization)
Solidity 会确定唯一的父类调用顺序,
即D → C → B → A(从右到左的深度优先)。
👉 因此,如果你在 D 中写:
1 | |
那么执行顺序是:
1 | |
即最后会返回 "C"(因为从右往左继承,C 在右边优先)。
🧭 五、总结表
| 名称 | 含义 |
|---|---|
| 菱形继承 | 一个基类被两个路径间接继承 |
| 主要问题 | 函数来源不唯一(A 被重复继承) |
| 解决方案 | 使用 override(A, B) + 线性化继承顺序 |
| 调用顺序 | 从右到左深度优先(super 调用链遵循 C3 线性化) |
如果你想更直观看这个继承路径(比如在 Remix 或图中看到执行顺序),
我可以帮你画一张调用链示意图(箭头+函数流向),让你看清 super.say() 实际走哪条路径。