java 虚继承_引入虚继承后会造成怎样的影响

描述

从这部分开始我们除了利用内存的信息打印来进行探索外,更多的会通过跟踪和观察编译器产生的汇编代码来理解编译器对这些语言特性的实现方式。汇编方面知识的讨论超出了本文的范围,我只对和我们讨论相关的汇编代码进行解析。理解本文要讨论的知识并不需要有很完整的汇编知识,但必须了解起码的概念。

下面我们看看引入虚继承后的影响。为了有所对比我们首先看看普通成员函数的调用情况。

执行如下代码,它包括了对象的普通成员函数调用,类的静态成员函数调用、通过指针调用普通成员函数:

1744e3f24d4dbddb8b710b17fa2b0f56.png

结果如下:

e6f6a11786f6cf15f94d636046e70d34.png

7c3fd4cd9503b069791d3922f9235524.png

这是obj对象的内存地址。

首先我们看看对象的普通成员函数调用,obj.foo();,对应的汇编代码为:

第1行把对象的地址存入ecx寄存器,执行完这行指令后,我们要以看到ecx中的值为0x0012F843,就是前面打印出的值。如果函数需要传递参数,我们还会在前面看到一些push指令。在第2行我们可以看到call的是一个直接的地址,这也就是静态绑定。即函数的调用地址在编译时已经被编译器决议。

跟踪进去我们要以看到是一条跳转指令,继续执行可以看到真正的函数代码部分,如下(注:为了讨论方便我在第行前面加了一个行号):

322f84759f8e483c65309344dc0f344b.png

我们看看第7行,把ecx寄存器入栈,后面4行初始化了函数的堆栈中的保存局部变量的部分。第12行弹出ecx值,到这里时ecx的值保持为在函数调用前存入的对象内存地址,第13行就是保存this指针的值,作为一个局部变量。这样我们就知道了VC7.1不是象传递普通函数那样通过压栈来传递this 指针,而是通过ecx寄存器来传递。第14、15行利用这个this指针给对象的成员变量进行了赋值。

再看看静态成员函数调用的汇编代码:

f56ef60e1aeba62d212c43cc289e462e.png

非常直接,因为它不需要处理this指针,跟踪到函数的汇编代码,可以看到同样不需要处理this指针。具体的代码这里就不列出来了。

再看看通过指针调用普通成员函数pt-》 foo();,产生的汇编代码如下:

2ec9dee0b6b5b09510192f86c266a5f5.png

和通过对象调用普通成员函数的代码差不多。不过存对象地址到ecx寄存器地,是通过解引用pt指针来找到对象地址的。

打开APP阅读更多精彩内容

点击阅读全文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值