C++多继承中的内存布局

● 一个对象,如果它的类有多个基类则有多个虚函数表指针

● 在多继承中,对应各个基类的vptr按继承顺序依次放置在类的内存空间中,且子类与第一个基类共用一个vptr(第二个基类有自己的vptr)

先看一个例子:

class A1
{
public:
	virtual void funcA1(){}
	virtual void funcA11(){}
public:
	int a1;
};

class A2
{
public:
	virtual void funcA2(){}
	virtual void funcA22(){}
public:
	int a2;
};

class B : public A1 ,public A2
{
public:
	virtual void funcA1(){}
	virtual void funcA2(){}
	virtual void funcB(){}
public:
	int b;
};

在此情况下,类B的内存结构为:

我们来验证一下:

typedef void(**vptr)();
int main()
{
	B* pb = new B; //值等于vptr1
    A1* a1 = pb; //值等于vptr1
    A2* a2 = pb; //值等于vptr2
	return 0;
}

先看看这三个指针都指向了什么内容:

可以看到三个指针都指向了一个虚函数表,由上图知0x400c30偏移了B的虚函数表16个字节,因此B的虚函数表的地址为0x400c20,我们接下来从这个地址开始依次打印出B的虚函数中的内容:

这意味着:

Address

Value

Meaning

0x400c20

0

top_offset

0x400c28

0x400ce0

typeinfo for B

0x400c30

0x400a34

B::funcA1

0x400c38

0x4009da

A1::funcA11

0x400c40

0x400a52

B::funcA2

0x400c48

0x400a76

B::funcB

0x400c50

-16

top_offset

0x400c58

0x400ce0

typeinfo for B

0x400c60

0x400a6f

non-virtual thunk to B::funcA2()

0x400c68

0x400a16

A2::funcA22

上述内容已经验证了是存在两个虚表的,A2的虚表中funcA2并不直接指向B::funcA2(), 而是指向一个thunk:

通过汇编代码可以看到,首先是将this指针偏移了0x10 (16, 即top_offset) 个字节,再跳转到B::funcA2()。

thunk的意义在于虚函数实际上是要传入this指针的,我们要调用子类当中的实现那么必须先将父类指针转化为子类指针,这通过一次this指针偏移就可以完成。

我们再看funcA22:

可以看到funcA22是直接指向A2::funcA22()的.

#面经##cpp##面试##八股##面试题刺客退退退#
全部评论

相关推荐

07-09 20:50
门头沟学院 Java
码农索隆:1.教育背景和荣誉证书合二为一。 2.获奖项目理一遍,你做了什么,对你求职的岗位有什么帮助,没有就删掉。 3.技能特长和教育背景交换位置。 4.技能特长写的太差,上网上找简历参考。都不用问你别的,一个redis就能把你问住,写写你具体会redis哪些方面的知识。
点赞 评论 收藏
分享
评论
3
8
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务