MST

星途 面试题库

面试题:C++ 虚基类继承下访问权限与对象布局的关联

考虑一个复杂的 C++ 虚基类继承结构:类 X 是虚基类,类 Y 和类 Z 虚继承自 X,类 W 多重继承自 Y 和 Z。假设 X 有一个 public 成员函数 print(),Y 和 Z 分别对 print() 进行了重写。请分析在 W 的对象内存布局中,虚基类 X 的部分是如何存储的,以及这种存储方式对访问权限和函数调用的影响机制是什么?
39.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 虚基类 X 在 W 对象内存布局中的存储

在这种复杂的虚基类继承结构中,虚基类 X 的数据成员在 W 对象的内存布局中只会出现一次,无论从多少条路径继承它。这是虚继承的关键特性,避免了数据成员的重复存储。

具体来说,W 对象的内存布局通常包含指向虚基类子对象(这里是 X)的指针(虚基表指针)。这个指针指向一个虚基表,虚基表中存储了虚基类 X 相对于 W 对象起始地址的偏移量。通过这种间接的方式,即使 W 从多个路径继承 X,也能确保 X 的唯一性。

2. 对访问权限的影响机制

  • 成员访问:由于虚基类 X 是 public 继承(因为 X 的成员函数 print() 是 public),W 的对象可以直接访问 X 的 public 成员。例如,W 的对象可以调用 X 的 public 成员函数 print()。这种访问权限遵循 C++ 的继承访问控制规则,与普通继承类似,但由于虚继承保证了 X 的唯一性,不存在访问歧义。
  • 继承链访问:在虚继承体系中,从 W 到 X 的继承路径是明确且唯一的,这使得编译器能够正确解析对 X 成员的访问。无论是通过 Y 还是 Z 的路径,对 X 成员的访问都是统一的,不会因为多重继承路径而产生访问冲突。

3. 对函数调用的影响机制

  • 函数重写与动态绑定:Y 和 Z 分别重写了 X 的 print() 函数。当通过 W 的对象调用 print() 时,动态绑定机制会根据对象的实际类型来决定调用哪个版本的 print()。如果 W 的对象的实际类型是 W 本身,并且 Y 和 Z 对 print() 的重写不同,那么编译器会根据虚函数表来确定调用哪个版本。
  • 虚函数表的作用:W 的对象有自己的虚函数表,虚函数表中存储了指向各个虚函数(包括从 X 继承而来并可能被重写的函数)的指针。在运行时,通过对象的虚函数表指针找到对应的虚函数表,进而找到要调用的函数版本。由于虚继承,从 X 继承的虚函数在虚函数表中的位置是固定且明确的,确保了正确的函数调用。