-
-
[原创]我们聊聊继承吧,从继承的角度出发再来聊聊多态
-
发表于:
2019-10-15 21:55
4080
-
[原创]我们聊聊继承吧,从继承的角度出发再来聊聊多态
上面的代码中子类虽然没有写构造函数和析构函数,但是编译器还是自动生成了它们,子类构造函数、析构函数和父类的构造函数、析构函数调用顺序如下:
父类构造函数 -> 子类构造函数 -> 子类析构函数 -> 父类析构函数
我们关注的重点并不在这里,而是子类对象和父类对象的关系。
走进ShowNumber函数:
在子类调用父类函数时,直接传递了子类的this指针,我们走进这个SetNumber :
执行结束回到ShowNumber继续执行
由此我们看出父类的nNumber赋值到this的前4个字节,而子类的nNumberChild赋值到this的第四个字节开始的后面四个字节。
那么此时this的内存结构如下图:
由此,我们可以总结出,父类对象在子类对象开始处,那么将上例中的CChild的类修改为下面的样子,则他们的内存结构时完全一样的。
这种内存结构的优势是什么?
很明显,子类对象调用父类的函数,直接传递子类的对象地址就可以了,那么子类对象指针可以强制转换为父类对象指针来使用,反之则不行。
------------------->分割线
再来聊聊多态,上代码:
先来看看输出:
是不是意料之中的结果?
来看看内部实现吧,先从cChild0的构造函数开始吧:
首先调用了父类的构造函数,然后赋值虚表为本类(cChild0)的虚表。
走进cBase的构造函数:
在构造函数中只做一件事,就是赋值虚表为本类(cBase)的虚表。
总结下,在cChild0的构造函数中做了以下的事情:
调用父类构造函数 -> 在父类的构造函数中设置虚表为本类(cBase)的虚表 -> 设置虚表为本类的(cChild0)虚表
需要注意的是,在上文中设置两次虚表都是cChild0 this指针的前四个字节。
在cChild1中做了同样的事情,就不再次赘述了。
那么现在已经很清晰了,这两个子类对象在构造函数调用之后会将虚表都设成自己的虚表。
现在我们来看看GoPrint函数吧:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-10-16 01:25
被Hasic编辑
,原因: