gpt4 book ai didi

c++ - Itanium C++ ABI 主要虚拟基础

转载 作者:太空宇宙 更新时间:2023-11-04 13:00:20 25 4
gpt4 key购买 nike

我正在阅读 here关于如何选择主要碱基:

"...2. If C is a dynamic class type:

a. Identify all virtual base classes, direct or indirect, that are primary base classes for some other direct or indirect base class. Call these indirect primary base classes.

b. If C has a dynamic base class, attempt to choose a primary base class B. It is the first (in direct base class order) non-virtual dynamic base class, if one exists. Otherwise, it is a nearly empty virtual base class, the first one in (preorder) inheritance graph order which is not an indirect primary base class if any exist, or just the first one if they are all indirect primaries..."

在更正之后:

"Case (2b) above is now considered to be an error in the design. The use of the first indirect primary base class as the derived class' primary base does not save any space in the object, and will cause some duplication of virtual function pointers in the additional copy of the base classes virtual table.

The benefit is that using the derived class virtual pointer as the base class virtual pointer will often save a load, and no adjustment to the this pointer will be required for calls to its virtual functions.

It was thought that 2b would allow the compiler to avoid adjusting this in some cases, but this was incorrect, as the virtual function call algorithm requires that the function be looked up through a pointer to a class that defines the function, not one that just inherits it. Removing that requirement would not be a good idea, as there would then no longer be a way to emit all thunks with the functions they jump to. For instance, consider this example:

struct A { virtual void f(); };

struct B : virtual public A { int i; };

struct C : virtual public A { int j; };

struct D : public B, public C {};

When B and C are declared, A is a primary base in each case, so although vcall offsets are allocated in the A-in-B and A-in-C vtables, no this adjustment is required and no thunk is generated. However, inside D objects, A is no longer a primary base of C, so if we allowed calls to C::f() to use the copy of A's vtable in the C subobject, we would need to adjust this from C* to B::A*, which would require a third-party thunk. Since we require that a call to C::f() first convert to A*, C-in-D's copy of A's vtable is never referenced, so this is not necessary."

能否请您举例说明这指的是什么:“删除该要求不是一个好主意,因为那样就不再有办法用它们跳转到的函数发出所有 thunk ”?

此外,什么是第三方 thunk

我也不明白引用的示例试图显示什么。

最佳答案

A 是一个几乎是空的类,它只包含一个 vptr 而没有可见的数据成员:

struct A { virtual void f(); };

A 的布局是:

A_vtable *vptr

B 有一个几乎是空的基类用作“主要”:

struct B : virtual public A { int i; };

这意味着 B 的布局从 A 的布局开始,因此指向 B 的指针是指向A(汇编语言)。 B 子对象的布局:

B_vtable *A_vptr
int i

A_vptr 显然会指向一个B vtable,它与A vtable 二进制兼容。

B_vtable 扩展了 A_vtable,添加了所有必要的信息以导航到虚拟基类 A

B 完整对象的布局:

A base_subobject
int i

同样适用于 C:

C_vtable *A_vptr
int j

C 完整对象的布局:

A base_subobject
int j

D中显然只有一个A子对象,所以一个完整对象的布局是:

A base_subobject
int i
not(A) not(base_subobject) aka (C::A)_vptr
int j

not(A) 是一个A 几乎为空的基类的表示,即A 的vptr,但不是a true A 子对象:它看起来像一个A 但可见的A 是上面的两个词。这是一个幽灵 A!

(C::A)_vptr 是指向具有 C 布局 vtable 的 vtable 的 vptr(因此也是具有 A 布局 vtable 的 vptr ),但对于 A 最终不是主要基础的 C 子对象:C 子对象已失去托管 的特权一个基类。所以很明显,通过 (C::A)_vptr 对虚函数定义的虚函数调用 A(只有一个:A::f()) 需要一个 this 调整,带有一个接收指向 not(base_subobject) 的指针的“C::A::f()” > 并将其调整为 A 类型的真实 base_subobject,即(示例中上面的两个词)。 (或者,如果 D 中有覆盖程序,则 D 对象位于完全相同的地址,示例中上面的两个词。)

所以给定这些定义:

struct A { virtual void f(); };
struct B : virtual public A { int i; };
struct C : virtual public A { int j; };
struct D : public B, public C {};

应该使用不存在的 A 主基的幽灵左值吗?

D d;
C *volatile cp = &d;
A *volatile ghost_ap = reinterpret_cast<A*> (cp);
ghost_ap->f(); // use the vptr of C::A: safe?

(此处使用volatile 以避免编译器传播类型知识)

如果对于 C 的左值,对于从 A 继承的虚函数,调用是通过 C vptr 完成的也是一个 C::A vptr,因为 AC 的“静态”主基,那么代码应该可以工作,因为一个 thunk已生成从 CD

在实践中它似乎不适用于 GCC,但是如果您在 C 中添加覆盖程序:

struct C : virtual public A {
int j;

virtual void f()
{
std::cout << "C:f() \n";
}
};

之所以有效,是因为这样的具体函数在 C::A 的 vtable 的 vtable 中。

即使只有一个纯虚拟覆盖:

struct C : virtual public A {
int j;
virtual void f() = 0;
};

D 中的具体覆盖,它也可以工作:纯虚拟覆盖足以在 C::A 的 vtable 中拥有正确的条目。

测试代码:http://codepad.org/AzmN2Xeh

关于c++ - Itanium C++ ABI 主要虚拟基础,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44433386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com