【问题标题】:vtable: Underlying algorithmvtable:底层算法
【发布时间】:2017-04-17 11:02:37
【问题描述】:

我对 vtables 的理解是,如果我有一个带有虚函数 speak() 以及子类 Lion 和 HouseCat 的 Cat 类,那么就会有一个 vtable 将 speak() 映射到每个子类的正确实现。所以打个电话

cat.speak()

编译为

cat.vtable[0]()

即在vtable位置0查找并在该位置调用函数指针。

我的问题是:多重继承会发生什么?

让我们添加一个类 Pet。 Pet 有虚函数 speak() 和 eat()。 HouseCat 扩展了 Pet,而 Lion 没有。现在,我需要确保

pet.eat()

编译为

pet.vtable[1]()

即vtable[0]需要speak()。 Pet.eat 需要是 slot 1。那是因为 cat.speak() 需要访问 vtable 中的 slot 0,如果对于 HouseCat,slot 0 恰好是eat,这将出现可怕的错误。

编译器如何确保 vtable 索引匹配在一起?

【问题讨论】:

  • 简短的回答是编译器确保它,因为这是编译器的工作。这就是它应该做的。所以它做到了。编译器在它自己实例化时为超类创建单独的 vtable,当它作为子类的一部分实例化时,并在实例化时将适当的 vtable 分配给超类实例。
  • 更简短的答案是没有指定 vtable,如果存在则依赖于实现。有关至少一种实现的详细信息,请参阅 Stanley Lippman,C++ 对象模型内部。
  • 如果您想了解所有详细信息,请在 Itanium C++ ABI 中描述一种方法。
  • 该对象可能包含多个指向 vtable 的指针 - 实际上每个基类都将有一个带有虚函数的指针。
  • 如果B派生自A,那么B就是一个A:这意味着A的每个细节都在B中复制,特别是vptr和vtable。那么如果B 派生自A1A2A3,那么Ax 的每个细节都会在B 中重现,所以它最终会得到(至少)与基础子对象一样多的 vptr .

标签: c++ compiler-construction multiple-inheritance vtable vptr


【解决方案1】:

规范没有设置任何内容,但通常编译器会为每个直接的非虚拟基类生成一个 vtable,为派生类生成一个 vtable - 然后为第一个基类生成一个 vtable,为派生类生成一个 vtable类将被合并。

更具体地说,编译器在构造类时生成的内容:

  • [vptr | Cat fields]
     [0]: speak()
    
  • 宠物

    [vptr | Pet fields]
     [0]: eat()
    
  • 狮子

    [vptr | Cat fields | Lion fields]
     [0]: speak()
    
  • 家猫

    [vptr | Cat fields | vptr | Pet fields | HouseCat fields]
     [0]: speak()        [0]: eat()
    

编译器在调用/强制转换时生成的内容(变量名是静态类型名):

  • cat.speak()
    • obj[0][0]() - 适用于猫、狮子和 HouseCat 的“猫”部分
  • pet.eat()
    • obj[0][0]() - 对 Pet 和 HouseCat 的“宠物”部分有效
  • lion.speak()
    • obj[0][0]() - 对 Lion 有效
  • houseCat.speak()
    • obj[0][0]() - 适用于 HouseCat 的“猫”部分
  • houseCat.eat()
    • obj[Cat size][0]() - 适用于 HouseCat 的“宠物”部分
  • (Cat)houseCat
    • obj
  • (Pet)houseCat
    • obj + Cat size

所以我猜让您感到困惑的关键是 (1) 多个 vtable 是可能的,并且 (2) 上播实际上可能返回不同的地址。

【讨论】:

  • "那么第一个基类的虚表和派生类的虚表将被合并"“第一个[非虚拟]基类”通常被称为主要基类
猜你喜欢
  • 2022-01-22
  • 2020-12-15
  • 1970-01-01
  • 1970-01-01
  • 2023-01-26
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多