|
<br />多态性(Polymorphism)是初学者最难理解的C++特性之一,“多态性”这个词似乎有点怪异,也许这就是令人难懂的原因吧,其实这个特性完全可以用别的方法描述(如以后将采用的实现机制描述),这样可以更直接的了解其本质。程序员们是一群很怪的家伙,做事情总是采取难理解的方法,有时甚至只是为好玩而使事情搞得很复杂。C语言程序员甚至可以参加一种年度竞赛,谁写的程序最难懂,谁就得一等奖。程序设计语言是通过书、杂志和论文等方式加以推广的,感兴趣的人越多越有利于推广。听起来很怪异的词更可能引起人们的兴趣,促使人们研究语言的新特性。如果有足够多的人发生了兴趣,语言使用者的数量达到了一定程度,该语言就成功了。这就是C++语言的演化过程,也许多态性这个术语在增加语言使用者方面起到了一定的作用。<br /><br />多态性是指C++的代码可以根据运行情况的不同执行不同的操作。这通常不是由此代码的编写程序员直接控制的,而必须根据此代码的最终衍生情况,依靠C++对象对自身进行跟踪,最终确定相关的操作。与其说多态性是类的特性,不如说它是类成员函数的特性。多态性是通过类的体系结构来实现的,不过只有类的成员函数可以具有多态性,而不是整个类都具有相关特性。下面分几个方面逐步阐述相关的概念和实现。<br /><br /><br />为何要用多态性<br /><br />先看一下在封装中所提到的那个状态机的直接包装程序:<br /><br />enum status_type { S0, S1, S2, S3, S4,…,Sn };<br /> <br />class class_SM<br />{<br /> protected:<br /> <br /> status_type status;<br /> <br /> virtual int Fy( int x );<br /> virtual void Fs( int x );<br /> <br /> public:<br /> <br /> class_SM( void ) { status = S0; }<br /> class_SM( status_type S ) { status = S; }<br /> <br /> int Do_it( int x );<br /> <br /> ~class_SM() {}<br />};<br /><br />int class_SM :: Fy( int x )<br />{<br />// return Fy( x, status )<br /><br /> return x;<br />}<br /><br />void class_SM :: Fs( int x )<br />{<br />// status <- Fs( x, status )<br />}<br /><br />int class_SM :: Do_it( int x )<br />{<br /> int result;<br /> <br /> result = Fy( x ); Fs( x );<br /> <br /> return result;<br />}<br /><br />现在去掉关键字virtual,采用形式化的描述将程序形式简化如下:<br /><br />class class_SM<br />{<br /> Fy;<br /> Fs;<br /> <br /> Do_it { Fy; Fs; } <br />};<br /><br />其中Fy和Fs是类class_SM中定义的两个成员函数。而Do_it同样也是class_SM的一个成员函数,不同的是其还调用了函数Fy和Fs。在论述继承时,给出了相应的派生类,现在同样用形式化的描述再现如下。<br /><br />class class_My_SM1 : public class_SM<br />{<br /> Fy;<br /> Fs;<br />};<br /><br />其中在类class_My_SM1中,对成员函数Fy和Fs进行了重新定义。由于class_SM是其基类,所以其基类中的成员函数Do_it被原封不动的继承了下来。如果采用前面说过的类成员函数的简单继承和覆盖概念,class_My_SM1虽然自定义了两个新的成员函数class_My_SM1::Fy和class_My_SM1::Fs,但最终却是徒劳。因为其继承来的成员函数Do_it所调用的还是基类的成员函数class_SM::Fy和class_SM::Fs。为了能够使得继承而来的成员函数调用类中新定义的Fy和Fs,就必须引入一种全新的调用机制。为了区别于一般的成员函数的调用,在必须采用特殊调用机制的成员函数前加上一个特殊的关键字——virtual,相关函数被称之为虚函数。采用虚函数后,上面例子的形式化描述再表如下:<br /><br />class class_SM<br />{<br /> virtual Fy;<br /> virtual Fs;<br /> <br /> Do_it { Fy; Fs; } <br />};<br /><br />class class_My_SM1 : public class_SM<br />{<br /> virtual Fy;<br /> virtual Fs;<br />};<br /><br />class_My_SM1 My_SM1;<br /><br />由于引入了多态调用机制,对象My_SM1的成员函数Do_it将调用所属类class_My_SM1中重新定义的虚函数Fy和Fs,这样才真正实现了其功能的更新。<br /><br />这里要进一步重申的是,虚成员函数(简称虚函数)一般是被类中其他成员函数所调用的。反过来说,如果一个成员函数只是作为顶层函数出现,就没有必要将其归入虚函数之列,虽然在派生类中可能会对它进行覆盖。<br />
|