C++多态

来源:互联网 发布:testv淘宝店地址 编辑:程序博客网 时间:2024/06/07 03:05

 

一、  什么是多态?

多态(Polymorphism)按字面的意思是“多种状态”。在JAVA等面向对象语言中,接口的多种不同的实现方式即为多态。“多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自《Delphi4 编程技术内幕》)”。简单的说就是:允许将子类类型的指针赋值给父类类型的指针。多态性在C++中通过虚函数(Virtual Function)来实现,在JAVA中通过interface和implements来实现。

换种方式说:多态就是允许将父对象设置成为和一个或多个它的子对象相等的技术,多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。c++中多态更容易理解的概念为允许父类指针或名称来引用子类对象,或对象方法,而实际调用的方法为对象的类类型方法。

多态性也分静态多态性和动态多态性两种。静态多态性是指定义在一个类或一个函数中的同名函数,它们根据参数表(类型以及个数)区别语义,并通过静态联编实现,例如,在一个类中定义的不同参数的构造函数。动态多态性是指定义在一个类层次的不同类中的重载函数,它们一般具有相同的函数,因此要根据指针指向的对象所在类来区别语义,它通过动态联编实现。一般函数的多态性是静态多态性;类的多态性是动态多态性。

“多态性”一词最早用于生物学,指同一种族的生物体具有相同的特性。在面向对象理论中,多态性的定义是:同一操作作用于不同的类的实例,将产生不同的执行结果,即不同类的对象收到相同的消息时,得到不同的结果。多态性包含编译时的多态性、运行时的多态性两大类。

动态多态是指发出同样的消息被不同类型的对象接收时,有可能导致完全不同的行为。即,在用户不作任何干预的环境下,类的成员函数的行为能根据调用它的对象类型自动作出适应性调整,而且调整是发生在程序运行时。  

多态是面向对象程序设计的重要特征之一。是扩展性在“继承”之后的又一重大表现。

二、  多态的作用和优点是什么?

把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。

赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。也就是说,父亲的行为像儿子,而不是儿子的行为像父亲。   

举个例子:从一个基类中派生,响应一个虚命令,产生不同的结果。  

比如从某个基类继承出多个对象,其基类有一个虚方法Tdoit,然后其子类也有这个方法,但行为不同,然后这些子对象中的任何一个可以赋给其基类的对象,这样其基类的对象就可以执行不同的操作了。实际上你是在通过其基类来访问其子对象的,你要做的就是一个赋值操作。  

使用继承性的结果就是可以创建一个类的家族,在认识这个类的家族时,就是把导出类的对象当作基类的的对象,这种认识又叫作upcasting。这样认识的重要性在于:我们可以只针对基类写出一段程序,但它可以适应于这个类的家族,因为编译器会自动就找出合适的对象来执行操作。这种现象又称为多态性。而实现多态性的手段又叫称动态绑定(dynamic binding)。  简单的说,建立一个父类的对象,它的内容可以是这个父类的,也可以是它的子类的,当子类拥有和父类同样的函数,当使用这个对象调用这个函数的时候,定义这个对象的类(也就是父类)里的同名函数将被调用,当在父类里的这个函数前加virtual关键字,那么子类的同名函数将被调用。

多态性有两种,一种是类的多态性,一种是函数的多态性。

三、  类的多态性

类的多态性和虚函数相关,了解多态性先了解虚函数的概念。

虚函数是在基类中定义的,目的是不确定它的派生类的具体行为。例:

定义一个基类:class Animal//动物。它的函数为breathe()//呼吸。

再定义一个类class Fish//鱼 。它的函数也为breathe()

再定义一个类class Sheep //羊。它的函数也为breathe()

为了简化代码,将Fish,Sheep定义成基类Animal的派生类。

然而Fish与Sheep的breathe不一样。所以基类不能确定该如何定义breathe,所以在基类中只定义了一个virtual breathe,它是一个空的虚函数。具本的函数在子类中分别定义。C++程序运行时先找到当前类,如果它有基类,再找它的基类,最后运行的是基类中的函数。这时,它在基类中找到的是virtual标识的函数,它就会再回到子类中找同名函数。派生类也叫子类。基类也叫父类。这就是虚函数的产生,和类的多态性(breathe)的体现。

这里的多态性是指类的多态性。

最主要的使用是为不同派生使用同样的驱动,即一个单一接口或变量。

 

如void AdvancedDraw()函数可以为不同派生内做高级绘图操作,这些派生类有,CLine,CCircle, CAngle等。则这样的函数为:

void AdvancedDraw(CLine &c);

void AdvancedDraw(CCircle &c);

vodi AdvancedDraw(Cangle &c);

以后每增加一个派生类需要增加一个处理函数,但是,如果利用多态,则只要一个函数

void AdvancdDraw(CShape &c)

{

// others

 c.draw();

}

这样会自动根据对象类型调用不同派生类的draw();

还有如

一个模块根据用户输入决定绘制操作,不利用多态则为:

 

CLine a;

CCircle b;

Cangle c;

swtch(sel)

{

  case 1: a.draw(); break;

  case 2: b.draw(); break;

  case 3: c.draw(); break;

}

以后增加新派生类,在这个模块中还需要增加变量,诸如d, e, f等。但利用多态则,只要一个变量来处理。如

CShape *a;

swtch(sel)

{

  case 1: a = new CLine; break;

  case 2: a = new CCircle; break;

  case 3: a = new Cangle; break;

}

a->draw();

这样代码需要修改的地方很少,减少出错的概率。

四、  函数的多态性

函数的多态性是指一个函数被定义成多个不同参数的函数,它们一般被存在头文件中,当你调用这个函数,针对不同的参数,就会调用不同的同名函数。例:Rect()//矩形。它的参数可以是两个坐标点(point,point)也可能是四个坐标(x1,y1,x2,y2)这叫函数的多态性与函数的重载。


杭州  2011.9