gpt4 book ai didi

c++ - 编译器构造虚表

转载 作者:太空宇宙 更新时间:2023-11-04 12:12:21 26 4
gpt4 key购买 nike

当派生类继承了n个基类的属性,每个基类都有一个虚函数,在为派生类构造虚表时,编译器为什么要为每个基类单独构造一个虚表?为什么编译器不构建一个包含所有对 Base 类的虚函数及其自身的引用的虚表?

例如:在下面的程序中,派生类继承了3个基类,每个基类都有一个虚函数。

             class Base1
{
public:
virtual void base1_func1(){cout<<"In Base1:base1_func1:"<<endl;}
};

class Base2
{
public:
virtual void base2_func1(){cout<<"In Base2:base2_func1:"<<endl;}
};

class Base3
{
public:
virtual void base3_func1(){cout<<"In Base3:base3_func1:"<<endl;}
};

class Derived:public Base1, public Base2, public Base3
{
};

typedef void (*Func) (void);

int main()
{
Base1 b1;
Base2 b2;
Base3 b3;
Derived d;
Func f= NULL;

cout<<"Size of Base1 obj:"<<sizeof(b1)<<endl;
cout<<"Size of Base2 obj:"<<sizeof(b2)<<endl;
cout<<"Size of Base3 obj:"<<sizeof(b3)<<endl;
cout<<"Size of Derived obj:"<<sizeof(d)<<endl;
cout<<"Printing the VPTR Address of Base1 obj b1 :"<< *((int *)(&b1)+0)<<endl;
cout<<"Printing the Address of Base1 func1 in VTABLE:"<< (int *)*((int *)*((int *)(&b1)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&b1)+0)+0);
f();
cout<<"Printing the VPTR Address of Base2 obj b2 :"<< *((int *)(&b2)+0)<<endl;
cout<<"Printing the Address of Base2 func1 in VTABLE:"<< (int *)*((int *)*((int *)(&b2)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&b2)+0)+0);
f();
cout<<"Printing the VPTR Address of Base3 obj b3 :"<< *((int *)(&b3)+0)<<endl;
cout<<"Printing the Address of Base3 func1 in VTABLE:"<< (int *)*((int *)*((int *)(&b3)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&b3)+0)+0);
f();

cout<<"Printing the VPTR1 Address of Derived obj d :"<< *((int *)(&d)+0)<<endl;
cout<<"Printing the VPTR2 Address of Derived obj d :"<< *((int *)(&d)+1)<<endl;
cout<<"Printing the VPTR3 Address of Derived obj d :"<< *((int *)(&d)+2)<<endl;
cout<<"Printing the Address of Derived base1_func1 in VTABLE:"<< (int *)*((int *)*((int *)(&d)+0)+0)<<endl;
f = (Func)*((int *)*((int *)(&d)+0)+0);
f();
cout<<"Printing the Address of Derived base2_func1 in VTABLE:"<< (int *)*((int *)*((int *)(&d)+1)+0)<<endl;
f = (Func)*((int *)*((int *)(&d)+1)+0);
f();
cout<<"Printing the Address of Derived base3_func1 in VTABLE:"<< (int *)*((int *)*((int *)(&d)+2)+0)<<endl;
f = (Func)*((int *)*((int *)(&d)+2)+0);
f();

return 0;
}

Output:
Size of Base1 obj:4
Size of Base2 obj:4
Size of Base3 obj:4
Size of Derived obj:12
Printing the VPTR Address of Base1 obj b1 :134517392
Printing the Address of Base1 func1 in VTABLE:0x8048dfe
In Base1:base1_func1:
Printing the VPTR Address of Base2 obj b2 :134517424
Printing the Address of Base2 func1 in VTABLE:0x8048e2a
In Base2:base2_func1:
Printing the VPTR Address of Base3 obj b3 :134517456
Printing the Address of Base3 func1 in VTABLE:0x8048e56
In Base3:base3_func1:
Printing the VPTR1 Address of Derived obj d :134517512
Printing the VPTR2 Address of Derived obj d :134517524
Printing the VPTR3 Address of Derived obj d :134517536
Printing the Address of Derived base1_func1 in VTABLE:0x8048dfe
In Base1:base1_func1:
Printing the Address of Derived base2_func1 in VTABLE:0x8048e2a
In Base2:base2_func1:
Printing the Address of Derived base3_func1 in VTABLE:0x8048e56
In Base3:base3_func1:

输出清楚地表明编译器为派生类中继承的每个基类构造了一个单独的虚拟表。

最佳答案

我可能会遗漏一些东西,但不会:

cout<<"Printing the VPTR1 Address of Derived obj d :"<< *((int *)(&d)+0)<<endl;
cout<<"Printing the VPTR2 Address of Derived obj d :"<< *((int *)(&d)+1)<<endl;
cout<<"Printing the VPTR3 Address of Derived obj d :"<< *((int *)(&d)+2)<<endl;

您只是在打印“X”d 元素的地址。&d = d的地址(&d + X) = 继续到 X 元素,或者换句话说 + (X * sizeof(d))(int *)(&d + X) = 将此地址视为指向 int 的指针(而不是指向 d 的指针)*((int *)(&d + 2) = 获取 int 值(基本上是地址的值)。

我的意思是,如果您向 Derived 类添加更多私有(private)成员并由此增加 sizeof(d),您将获得不同的值,但是很明显,VPTR 没有移动。

==编辑==

不知道怎么做,但你需要找到正确的方法来找到VPTR地址

关于c++ - 编译器构造虚表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9312389/

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