2.2.7 虚函数与多态性、纯虚函数(2)
为什么输出的结果不是"fish bubble"呢?这是因为在我们将fish类的对象fh的地址赋给pAn时,C++(www.cppentry.com)编译器进行了类型转换,此时C++(www.cppentry.com)编译器认为变量pAn保存就是animal对象的地址。当在fn函数中执行pAn->breathe()时,调用的当然就是animal对象的breathe函数。
为了帮助读者更好地理解对象类型的转换,我们给出了fish对象内存模型,如图2.13所示。
|
| 图2.13 fish类对象的内存模型 |
当我们构造fish类的对象时,首先要调用animal类的构造函数去构造animal类的对象,然后才调用fish类的构造函数完成自身部分的构造,从而拼接出一个完整的fish对象。当我们将fish类的对象转换为animal类型时,该对象就被认为是原对象整个内存模型的上半部分,也就是图2.13中的"animal的对象所占内存"。当我们利用类型转换后的对象指针去调用它的方法时,自然也就是调用它所在的内存中的方法。因此,出现如图2.12所示的结果,也就顺理成章了。
现在我们在animal类的breathe()方法前面加上一个virtual关键字,结果如例2-17所示。
例2-17
- #include <iostream.h>
- class animal
- {
- public:
- void eat()
- {
- cout<<"animal eat"<<endl;
- }
- void sleep()
- {
- cout<<"animal sleep"<<endl;
- }
- virtual void breathe()
- {
- cout<<"animal breathe"<<endl;
- }
- };
- class fish:public animal
- {
- public:
- void breathe()
- {
- cout<<"fish bubble"<<endl;
- }
- };
-
- void fn(animal *pAn)
- {
- pAn->breathe();
- }
- void main()
- {
- animal *pAn;
- fish fh;
- pAn=&fh;
- fn(pAn);
- }