gpt4 book ai didi

c++ - 在多重继承的情况下选择 vptr

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

这与之前的许多问题类似,但它提出了一些我无法找到答案的问题。

#include <iostream>
using namespace std;

class Base1 {
public:
int b1_data;
virtual void b1_fn() {cout << "I am b1\n";}
};
class Base2 {
public:
int b2_data;
virtual void b2_fn() {cout << "I am b2\n";}
};
class Derived : public Base1, public Base2 {
public:
int d_data;
void b1_fn() {cout << "I am b1 of d\n";}
void b2_fn() {cout << "I am b2 of d\n";}
};

int main() {
Derived *d = new Derived();
Base1 *b1 = d;
/*My observation mentioned below is implementation dependant, for learning,
I assume, there is vtable for each class containing virtual function and in
case of multiple inheritance, there are multiple vtables based on number of
base classes(hence that many vptr in derived object mem layout)*/

b1->b1_fn(); // invokes b1_fn of Derived because d points to
// start of d's memory layout and hence finds vtpr to
// Derived vtable for Base1(this is understood)
Base2 *b2 = d;
b2->b2_fn(); // invokes b2_fn of Derived but how? I know that it "somehow"
// gets the offset added to d to point to corresponding Base2
// type layout(which has vptr pointing to Derived vtable for
// Base2) present in d's memory layout.
return 0;
}

具体来说,b2如何指向Derived for Base2的vtable的vptr到b2_fn()?我试过从 gcc 中查看 memlayout 转储但无法弄清楚。

最佳答案

编译器在多重继承的情况下,构建他的 vtables 以便每个子对象都有一个合适的 vtable。当然,这是依赖于实现的(就像 vtables 本身),但它会像这样组织:

  • Base1 对象有一个指向 vtable 的 vptr,该 vtable 包含指向 Base1::b1_fn 的唯一指针>
  • Base2 对象有一个指向 vtable 的 vptr,该 vtable 包含指向 Base2::b2_fn 的唯一指针>
  • Derived 对象有一个指向 vtable 的 vptr,该 vtable 以对应于 Base1 的 vtable layout 开头,但使用 Base2 的 vtable 的缺失元素对其进行了扩展。对于“布局”,我的意思是 b1_fn() 的指针处于相同的偏移量,但它可能指向一个覆盖函数。因此,此处的表将包含 Derived::b1_fn,后跟 Derived::b2_fn。这种组合布局确保 Derived 中的 Base1 子对象可以与其子对象共享 vtable。
  • 但是 Derived 对象由 2 个子对象组成:所以 Base1 子对象后面会跟着一个 Base2 子对象,它有它自己的 vtable,使用 Base2 所需的布局,但同样使用 Base2::b2_fn 而不是原始布局。

当将 Derived 指针转换为 Base2 指针时,编译器将使它指向 Base2 子对象及其 vtable,通过应用在编译时确定的固定偏移量。

顺便说一句,如果您要进行向下转换,编译器会类似地使用另一个方向的固定偏移量,以找到 Derived 的开始。这一切都非常简单,直到您使用虚拟基地,其中固定偏移技术不再起作用。然后必须按照此 other SO answer 中的说明使用虚拟基指针

Dr.Dobb's article是对所有这些布局的最好解释和一些好的图片。

关于c++ - 在多重继承的情况下选择 vptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36091456/

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