WEB开发网
开发学院软件开发VC VC++深入详解:虚函数与多态性 阅读

VC++深入详解:虚函数与多态性

 2008-11-24 19:37:17 来源:WEB开发网   
核心提示: 读者可以猜想一下例2-16运行的结果,输出的结果应该是“animal breathe”,VC++深入详解:虚函数与多态性(2),还是“fish bubble”呢?运行这个程序,你将看到如图2.12所示的结果,如果对象类型是派生类,就调用派生类

读者可以猜想一下例2-16运行的结果,输出的结果应该是“animal breathe”,还是“fish bubble”呢?

运行这个程序,你将看到如图2.12所示的结果。

VC++深入详解:虚函数与多态性

图2.12 EX09程序的运行结果(一)

为什么输出的结果不是“fish bubble”呢?这是因为在我们将fish类的对象fh的地址赋给pAn时,C++编译器进行了类型转换,此时C++编译器认为变量pAn保存就是animal对象的地址。当在fn函数中执行pAn->breathe()时,调用的当然就是animal对象的breathe函数。

为了帮助读者更好地理解对象类型的转换,我们给出了fish对象内存模型,如图2.13所示。

VC++深入详解:虚函数与多态性

当我们构造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);
  }

用virtual关键字申明的函数叫做虚函数。运行例2-17这个程序,结果调用的是fish类的呼吸方法:

VC++深入详解:虚函数与多态性

图2.14 EX08程序的运行结果(二)

这就是C++中的多态性。当C++编译器在编译的时候,发现animal类的breathe()函数是虚函数,这个时候C++就会采用迟绑定(late binding)技术。也就是编译时并不确定具体调用的函数,而是在运行时,依据对象的类型(在程序中,我们传递的fish类对象的地址)来确认调用的是哪一个函数,这种能力就叫做C++的多态性。我们没有在breathe()函数前加virtual关键字时,C++编译器在编译时就确定了哪个函数被调用,这叫做早期绑定(early binding)。

C++的多态性是通过迟绑定技术来实现的,关于迟绑定技术,读者可以参看相关的书籍,在这里,我们就不深入讲解了。

C++的多态性用一句话概括就是:在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数。

上一页  1 2 

Tags:VC 深入 详解

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接