【问题标题】:Compile time subclass byte-offset with virtual inheritance具有虚拟继承的编译时子类字节偏移
【发布时间】:2021-11-13 05:46:35
【问题描述】:

是否可以在编译时计算继承层次结构中虚拟基的字节偏移量?

例子-

class A {};
class B : public virtual A {};
class C : public virtual A {};
class D : public virtual B, public virtual C {};

我想计算 B、C 和 D w.r.t 实例的字节偏移量。 A 在编译时,即不使用任何这些类的任何真实实例。

从我目前在网上阅读的内容来看,编译器在虚拟表的帮助下实现逻辑(由 static_cast 和 dynamic_cast 使用),并且由于这些类中没有任何一个 true 实例,因此没有要搭载的虚拟表。但希望有一些模板魔法可以使这项工作。

目的 - 我试图让这个 Custom RTTI 实现与虚拟继承一起工作。

【问题讨论】:

  • @S.M.:尊重。

标签: c++ gcc visual-c++ c++17 sfinae


【解决方案1】:

是否可以在编译时计算继承层次结构中虚拟基的字节偏移量?

不,因为不同的对象实例是不同的。它不是类的属性。

让我们看看你的例子。 B 有一个虚拟基类 A。所以B 必须与A 有一些字节偏移。 C 也是如此。

但是,D 通过B 和C 继承了虚拟A。 virtual 继承的全部意义在于,如果您继承同一个基类,那么到达该基类的所有路径都将引用动态类型的同一个子对象。所以D 只有一个A 实例。

但是它在哪里呢? B 和 C 使用的偏移量不能两者都是正确的。除非...偏移量本身存储在vtable中。

这(基本上)是虚拟继承的工作原理。当您创建D 时,D 负责分配所有virtually 继承对象的位置。这些偏移量与创建动态类型为B 或C 的对象时不同。

没有办法做你想做的事。并非没有实际创建对象实例。虽然 C++20 确实允许您在编译时创建虚拟类型的实例(只要它们具有可行的 constexpr 构造函数,因此您不能对所有内容都这样做),但您仍然无法做您需要的事情。如果您有指向两种不同类型的指针,要计算它们之间的字节偏移量,您必须将reinterpret_cast 这些指针指向整数或unsigned char*s。并且reinterpret_cast 在编译时被禁止(并且bit_cast 在给定指针类型或包含指针的类型时不是constexpr)。

【讨论】:

  • 欣赏详细解释。根据您的评论,D 的 vtable 具有存储 B 和 C 的偏移量。同样B 和C 也知道A 的存储位置。 A 'B(或 C)中的偏移量可能与 D 中的不同,但偏移量仍然是每个类型的 constant - 它不能是每个实例,因为只有每种类型一个 vtable。编译器正在计算这些偏移量并更新相应类型的 vtable。那么,有没有办法让编译器在编译时显示这些值?
  • @Shahji: "它不能针对每个实例,因为每个类型只有一个 vtable" 偏移量存储在 vtable 中。类的动态类型是将偏移量放在那里的类型。 B 和 C 将在该 vtable 中查找偏移量。这就是允许B 和C 在D 中引用相同的A 的原因。偏移量不能是“每种类型的常量”;它必须根据所使用的动态类型来确定。如果您创建B,则B 将使用与D 内部的B 不同的偏移量。
猜你喜欢
  • 1970-01-01
  • 2016-03-04
  • 2020-10-31
  • 2014-08-16
  • 1970-01-01
  • 2020-12-08
  • 2013-02-14
  • 2013-12-07
  • 1970-01-01
相关资源
最近更新 更多