C++中多态的底层实现

1.先来看一波比较容易出错的题

C++中多态的底层实现_第1张图片

会打印出来什么?

其实打印出来的是B->1;为什么呢?看我如何讲解的。

C++中多态的底层实现_第2张图片

2.思考为什么只有引用或则指针才能触发多态

C++中多态的底层实现_第3张图片

结论:子类赋值给父类对象切片,不会拷贝虚标

我听老师上面的解释是:如果拷贝虚表,那么父类对象虚表中是父类还是子类就不确定了。

但是我感觉有点晦涩,可能的能力还不够,我的理解就是,赋值本来就是一种重新创建一个新的对象,类型是不会变的,能强转就强转,不能就报错。但是引用和指针就不一样了,他传的是地址,那自然而然的虚表就会转过去,为什么呢?因为vfpter的地址就在类里面啊。看下面就会理解了,因为下面就要讲地址了。

3.虚标是存在内存的哪一个段中?

1.栈,堆,静态区(数据段),常量区(代码段)

首先我们要增加一个知识点:就是上面的A类在内存中是如何存储的;

C++中多态的底层实现_第4张图片

很多书上写的是静态区,但是我实验了一下,应该是在常量区的,可以跟着我实验一下子,然后你自行判断。

C++中多态的底层实现_第5张图片

我想一个相同的段,他们之间相差的地址应该不会太大的,所以我由此判断,他应该是存储在常量区的。

4.子类添加一个虚函数,但是虚标中没有添加是为什么?

1.首先  要增加的一个知识点就是,在vs编译器环境下,虚表的最后会用0来表示结尾,各个编译器不一样,g++好像就不是的,所以别把这种当成一定是这样的。

C++中多态的底层实现_第6张图片

2.现在我们再来看标题上的问题:

C++中多态的底层实现_第7张图片

因此,我们可以用一些特殊的办法来打印出来,验证一下我们这个想法:
C++中多态的底层实现_第8张图片

5.多继承的派生类中重写的虚函数地址为什么不一样?

C++中多态的底层实现_第9张图片

1.他们调用得是同一个函数,难道编译器写了两份函数吗?其实没有必要,所以我们又要从内存下手了啊。

C++中多态的底层实现_第10张图片

但是我们调到了地址,依旧没有我们想要的答案,感觉这个内存有点杂乱无章了,不清楚应该干嘛了,那么其实我们可以取汇编看一下情况,或许就能有所头目。

C++中多态的底层实现_第11张图片

由此可见,他Base2经历了一段操作,调到了同一个函数里面,但是有没有想过为什么呢?

看一眼这一步就会发现,sub是减去的意思,相当于把ecx减去了8,那ecx是什么呢?其实是存this指针的地方,我们调用的fun1是不是用的是Derive的this指针,所以要让this指针减去一个Base2的大小(8== 函数地址4加上成员变量b2  4字节)

但是我加了一个Base类,按道理他应该在调用第一个也会ecx减去然后指向Base也就是Derive这个类的this指针,但是他没有,所以我有充分的理由怀疑会不会寻找的就是最上面题目上讲的,找到是最基类虚函数的声明那一段。

C++中多态的底层实现_第12张图片

你可能感兴趣的:(c++,开发语言)