gpt4 book ai didi

c++ - 编译器如何解析访问非虚拟数据成员的虚拟函数 C++

转载 作者:搜寻专家 更新时间:2023-10-31 01:07:36 24 4
gpt4 key购买 nike

当我产生这个疑问时,我正在阅读 C++ 对象。假设有两个类

class X
{
virtual int def() { };
}

class Y
{
virtual int abc() { };
}
class Z : public X,public Y
{
virutal int abc() { return a };
int a;
}

现在我的理解是 Y 和 Z 在它们的虚拟表中都有对 Z::abc() 的引用,这有助于解析要调用的正确函数。考虑

Y *y = new Z;
Z *z = new Z;
y->abc() // I understand this is done by reaching the vptr of y by this = this + sizeof (X)
and z->abc() // z has its own vptr reachable

我的理解是,在这两种情况下都传递了“this”指针,并且在找到要调用的正确 abc() 之后,程序如何到达 int 值“a”? enter image description here

编译器如何根据传递的对象类型正确计算出“int a”的地址?

最佳答案

这都是实现细节,不同的编译器做不同的事情。有两种常见的方法可以解决该问题,但都取决于修复函数定义中 this 指针所指的内容。

一种方法是让 this 指针始终指向完整的对象(至少在该虚函数的最终覆盖层)。在这种方法中,在存在多重继承的情况下,vtable 中的条目不包含指向实际函数的指针,而是指向调整 this 指针然后跳转到的蹦床的指针覆盖者。这种方法的优点是对于最左边的非空基和在所有单继承的情况下,vtable 中的条目实际上是覆盖程序并且没有相关的成本。这是 Itanium C++ ABI 中采用的方法,它用于不同的操作系统,包括 Linux。

另一种方法是始终传递首先声明成员函数的子对象的地址。在这种情况下,调用者调整 this 指针以引用子对象 before 通过 vtable 跳转。与第一种情况一样,如果没有偏移量(第一个非空基,单继承),编译器不需要添加任何调整,也不会产生任何成本。在最终重写器的实现中,编译器使用声明函数的基指针的偏移量,而不是完整对象的偏移量。我相信 Windows/Visual Studio 就是这种情况,但不要相信我的话,因为我无权访问 VS C++ ABI 来确认这一点。

第三种方法是将调整直接存储在 vtable 中。这种方法不太常见,即使不需要更新(通过添加 0)也会产生调整偏移量的成本。我不知道目前有任何编译器使用这种方法。

关于c++ - 编译器如何解析访问非虚拟数据成员的虚拟函数 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19149733/

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