c++ virtual 动态绑定(类的底层实现)

	说到c++的动态绑定,就不得不提到类在内存中的存储了,因为动态绑定
从原理上来谈,与c++类的内存存储分别不开。
	首先,什么是类,我们知道,编译器会将c++的代码编译成汇编代码,
而汇编代码又分为 堆区、栈区、代码区、全局/静态区、常量区,其实类就
相当于是这些区域的数据的耦合。
	对于类的成员方法,一般放到代码区里面,而类的常量和静态变量(方法)
分别放置在常量区和静态全局区,但是类的变量一般是没有存储的,因为变量会
随着对象的不同而改变,所以平常所说的对象,其实就是堆区、栈区变量的集合体。
	对于对象的创建不同,他的存储位置也会不同,例如如果是 class *a = new class(),
这种类的创建方式,那么他的数据会保存在堆区里面,如果是 class a; 这种
创建方式,那么类的数据会保存在栈里面,对于这两种方式的区别,对于c++而言,
堆区的数据编译器不会自动回收,所以需要手动delete,第二种方式编译器会自动
回收数据。
	说了这么多,来一张图总概括一下

在这里插入图片描述

	谈完了类,再来谈谈对象,上面讲到了,所谓的对象其实就是变量的集合,但是
这些变量都有些什么呢?就是类的变量吗?其实不然,对象里面还包含了一个指向
类的 isa 指针和 指向虚表的 _vptr 指针,其中,isa 指针是用来调用方法的,而
_vptr 指针是用来 调用虚方法的,那么 this 指针呢?this 指针存放在寄存器中,并不
在堆栈中,所以他并不是对象的属性,只是在类对象活跃期间,能够通过寄存器查到
对象的地址而已。
	那么这两个指针是如何实现动态绑定和静态绑定的?
	静态绑定,在编译器工作期间,其实他是不认识所谓的函数名的,对于任何一个
函数,最终都会解释成为一系列的机内码,当将所有的逻辑都转换成为机内码之后,
编译器再根据机内码和符号表反推出汇编代码,在这个反推的过程中,每一个函数
名其实就被替换成了代码区代码开始的地址,所以我们平常看的类的方法,从某
种角度来讲其实类的方法名就是一个固定的地址值,当调用方法时相当于调用这个
地址,而c++的 virtual 关键字就是作用在这个编译过程中的,告诉编译器这里是要
进行动态绑定的,这时编译器就不会将他编译成一个固定的值,而是将这个地址
作为了一个动态的变量来对待的,只不过这个变量比较特殊,存在在虚表中。当对象
调用方法时,就会通过 _vptr 指针来找到,所以实际上,动态函数其实就和对象的
变量是一样的,区别如图

在这里插入图片描述

	经过上面的一系列操作,一个类就被固化成了内存中的一系列代码,类就变成了
静态的内存存储段,当程序动态运行的时候,创建了动态的对象,对象的数据是会
发生变化的,当要调用方法的时候,可以通过 isa 指针找到方法所在的代码段,然后
运行,如果碰到动态方法,其实就相当于特殊变量的调用,这时他会如同访问变量
一样去访问自己的 vptr,通过这个指针找到虚表,进而找到对应的虚函数地址运行,
这就是动态绑定。
	对于 vptr,可以当作普通的成员变量去理解,而对于 isa,则和这个普通的成员
是有所差别的,详见这个up的文章

isa

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值