1.先来看一波比较容易出错的题
会打印出来什么?
其实打印出来的是B->1;为什么呢?看我如何讲解的。
2.思考为什么只有引用或则指针才能触发多态
结论:子类赋值给父类对象切片,不会拷贝虚标
我听老师上面的解释是:如果拷贝虚表,那么父类对象虚表中是父类还是子类就不确定了。
但是我感觉有点晦涩,可能的能力还不够,我的理解就是,赋值本来就是一种重新创建一个新的对象,类型是不会变的,能强转就强转,不能就报错。但是引用和指针就不一样了,他传的是地址,那自然而然的虚表就会转过去,为什么呢?因为vfpter的地址就在类里面啊。看下面就会理解了,因为下面就要讲地址了。
3.虚标是存在内存的哪一个段中?
1.栈,堆,静态区(数据段),常量区(代码段)
首先我们要增加一个知识点:就是上面的A类在内存中是如何存储的;
很多书上写的是静态区,但是我实验了一下,应该是在常量区的,可以跟着我实验一下子,然后你自行判断。
我想一个相同的段,他们之间相差的地址应该不会太大的,所以我由此判断,他应该是存储在常量区的。
4.子类添加一个虚函数,但是虚标中没有添加是为什么?
1.首先 要增加的一个知识点就是,在vs编译器环境下,虚表的最后会用0来表示结尾,各个编译器不一样,g++好像就不是的,所以别把这种当成一定是这样的。
2.现在我们再来看标题上的问题:
因此,我们可以用一些特殊的办法来打印出来,验证一下我们这个想法:
5.多继承的派生类中重写的虚函数地址为什么不一样?
1.他们调用得是同一个函数,难道编译器写了两份函数吗?其实没有必要,所以我们又要从内存下手了啊。
但是我们调到了地址,依旧没有我们想要的答案,感觉这个内存有点杂乱无章了,不清楚应该干嘛了,那么其实我们可以取汇编看一下情况,或许就能有所头目。
由此可见,他Base2经历了一段操作,调到了同一个函数里面,但是有没有想过为什么呢?
看一眼这一步就会发现,sub是减去的意思,相当于把ecx减去了8,那ecx是什么呢?其实是存this指针的地方,我们调用的fun1是不是用的是Derive的this指针,所以要让this指针减去一个Base2的大小(8== 函数地址4加上成员变量b2 4字节)
但是我加了一个Base类,按道理他应该在调用第一个也会ecx减去然后指向Base也就是Derive这个类的this指针,但是他没有,所以我有充分的理由怀疑会不会寻找的就是最上面题目上讲的,找到是最基类虚函数的声明那一段。