先独立作答,再展开参考答案。八股原题沿用原笔记编号;扩展练习为本站根据对应考点编写。
Q21 · 基类句柄指向派生类对象时,virtual 有什么作用?
八股原题 · Q21 · 题型:问答
考点
- 静态类型与动态类型
- 方法重写和动态绑定
展开参考答案 · Q21
题目来源(原笔记记录)
- 小鹏汽车 · SOC验证 · 校招(virtual function/task 未声明 virtual 会出现什么问题)
- 芯动科技 · 数字IC验证 · 校招(讲解多态时结合 virtual 关键字说明子类重写)
- 字节跳动 · AI芯片研发 · 校招 · 一面(父类子类句柄关系;virtual 实现多态)
- 行云集成电路 · 数字IC验证 · 实习(面向对象多态的理解)
- 豪威科技 · 数字IC验证 · 校招 · 一面(父类句柄与子类句柄互相赋值,分析输出)
- 达摩院 · 数字IC验证 · 校招(多态概念、virtual 用法、父类/子类指针指向规则)
- 芯动科技 · 数字IC验证 · 校招 · 一面(OOP 多态理解)
- 面试书《Cracking Digital VLSI Verification Interview》· 第4章 Q74-Q76(对应题目:派生类覆盖是否必须加 virtual;基类句柄指向派生类对象;virtual 函数的调用顺序)
基类句柄决定”能看见哪些成员”,virtual 决定”运行时执行哪个类的方法”。
第一,静态类型 vs 动态类型。 b = c 赋值是合法的,因为 child “是一个” base;但句柄 b 的静态类型还是 base,只能访问 base 声明过的成员。
第二,virtual 的作用。 如果 base 的 print() 声明成 virtual 且 child 重写了它,b.print() 按对象动态类型执行 child 版本;没声明 virtual 就按句柄静态类型执行 base 版本——这就是”没写 virtual 会出现什么问题”的答案。
base b;
child c = new();
b = c;
b.print();第三,重写要求。 派生类重写 virtual 方法要保持兼容签名;通常基类声明 virtual 后派生类就保持虚方法语义,但显式写出来更利于阅读。
一句话:基类句柄决定”能看见哪些成员”,virtual 决定”运行时执行哪个类的方法”。
E21 · 静态绑定与动态绑定
扩展练习 · E21 · 题型:代码阅读 · 对应原题:Q21
考点
- 静态类型与动态类型
- 方法重写和动态绑定
class base;
virtual function int kind(); return 1; endfunction
function int plain(); return 10; endfunction
endclass
class child extends base;
function int kind(); return 2; endfunction
function int plain(); return 20; endfunction
endclass已执行 child c = new(); base b; b = c;,b.kind()、b.plain()、c.plain() 分别是什么?
展开参考答案 · E21
分别为 2、10、20。kind 在基类已声明 virtual,派生类重写仍保持虚方法语义;plain 非虚,按调用句柄的静态类型绑定。不能把基类句柄能否访问某成员与该成员是否动态派发混为一谈。