虚拟基类是如何存储的?

Posted

技术标签:

【中文标题】虚拟基类是如何存储的?【英文标题】:How is virtual base classes stored? 【发布时间】:2013-06-07 20:51:49 【问题描述】:

所以我知道,如果您有菱形继承问题并且您进行虚拟继承,它只会创建一个基类,但是它究竟是如何表示的?

在 vtable 中是否有一个指向基类的指针,当构建派生类之一时,它会查看该指针是否已经存在,如果不存在,它会创建它并使其指向基类?

【问题讨论】:

Mandatory reading。简短的回答:用魔法。 【参考方案1】:

你的开始是正确的。尽管实现细节可能会有所不同,但实际上是的,vtable(或无论如何在类元数据中)中的信息足以找到基类。

对于您的第二部分,AFAIK 在任何实现中都没有“查看指针是否已经存在”。 C++ 使派生最多的类负责构造所有虚拟基。因此,对于涉及RootMiddle1Middle2MostDerived 的普通菱形继承,用于构造MostDerived 实例的代码将:

构造Root并设置一个vptr指向MostDerived的vtable 构造Middle1Middle2 构造MostDerived的数据成员 执行MostDerived的构造函数体

我说“a vptr”而不是“vptr”,因为在Middle1 的构造过程中,Root 基类可用,但Middle1 的任何虚函数不要但请参阅MostDerived 中定义的覆盖。由实现来解决这个问题,您可以通过查看对象大小来自己试验有多少隐藏指针用于执行此操作,以及数量是否取决于Middle1 是否具有虚函数。

请注意,构造Middle1 实例的常用代码将:

构造Root 并设置vptr 指向Middle1 的vtable 构造Middle1的数据成员 执行Middle1的构造函数体。

当我们构造MostDerivedMiddle1 基类子对象时,我们只想执行其中两个步骤,而不是全部三个步骤。出于这个原因,您可能会发现具有多个构造函数的类的发出代码包含多个构造函数——一个用于最派生类型为类的对象,另一个用于类型为类的基类子对象.

【讨论】:

或者有时一个额外的函数参数说明是否构建虚拟碱基。 @aschepler:很公平。至关重要的是,该标准不允许您使用指向构造函数的指针,因此实现可以通过调用约定、多个入口点或额外参数来发挥它喜欢的任何技巧。从虚拟基础代码到普通构造函数的其余部分显然是一种策略。

以上是关于虚拟基类是如何存储的?的主要内容,如果未能解决你的问题,请参考以下文章

通过将对象显式存储为基类来抑制虚拟机制? [复制]

第五周学习视频

Ue4类设置找不到基类

有其他虚拟基类时如何避免对基类函数的模糊调用

使用接口/抽象基类是pythonic吗?

C#中基类属性值在子类中设置,如何在基类的方法中获取子类设置的值?