C++语言中多态性的分析

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

第13卷第1期广州航海高等专科学校学报

Vol .13 No .1

2005年6月

JOURNAL OF G UANGZ HOU MAR I TI M E COLLEGE

Jun .2005

文章编号:1009-8526(2005)01-0055-03

C++语言中多态性的分析

江勇驰

(广州航海高等专科学校交通运输管理系,广东广州510725)

摘 要:通过分析C++语言多态性的各种形式、特征及其在程序设计中的应用,说明多态性是对相似问题求解的有效方法.

关键词:C++;多态性;面向对象;虚函数中图分类号:TP311.1 文献标识码:A

 收稿日期:2005-03-10

 作者简介:江勇驰(1972-),男,助理馆员,主要从事自动化与计算机的实验教学和管理.

C++语言具有数据封装、继承及多态性三大特征[1]

,多态性同时考虑了类的数据封装与继承关系的设计,是C++最重要的特征.在程序中多态性是指同一符号或名字在不同情况下代表不同但相似的功能[2]

,是对相似问题的一种求解方法.本文主要分析C++语言的多态性支持在程序设计中的应用.

1 实现形式及其应用

在C++面向对象程序设计中,实现多态性有两

种基本形式:编译时多态性和运行时多态性[3]

.编译时多态性是指在程序编译阶段即可确定下来的多态性,包括强制多态和重载多态两种形式.运行时多态性是指必须等到程序动态运行时才可确定的多态性,主要通过继承结合动态绑定获得,分别体现在包含多态与类型参数化多态两方面.

1.1 强制多态

当表达式中存在不同类型的操作数时,为对此表达式进行求值,编译程序需要对其中的部分操作数强制进行类型转换,以保证运算符两边的操作数类型一致,但体现出来的却是完成了不同类型操作数间的运算,这就是C++中的强制多态性.C++中,“1+2”表示整数的加法,“1.0+2.0”表示浮点数的相加,而“1.0+2”需要作类型转换,实际进行浮点数加法,但却表示整数与浮点数的相加.这两种运算的内部实现是不同的,而且效率相差很大,不便用不同的符号表达.同一个运算符“+”可以同时具有不

同但相似的运算含义,体现的就是强制多态性

[3]

.

C++中规定了基本数据类型之间的转换规则:如果

运算符两边的操作数类型运算不一致,则总是将取值范围的最大值较小的类型转换为取值范围的最大值较大的类型,取值范围从大到小分别是:l ong double,double,fl oat,unsigned l ong,l ong,unsigned 和int .正是由于这种多态性,才简化了程序设计,可以

按相同的逻辑处理各种数据的加法.不过C ++中,强制多态性是有限的,不能用这一方法去解决许多类似问题.重载多态提供了另外一种途径.

1.2 重载多态

重载多态主要通过使用重载机制获得,包括函数重载和运算符重载两大类.

运算符重载允许重新定义C ++语言已有的运算符,以一种更加自然的方式使用自己定义的类类型.例如,加法运算符“+”表示整数或浮点数的加法,如果用户定义了一个复数类Comp lex,在类定义中对加法运算符“+”进行了重载,定义实现复数相加的操作Co mp lex operat or +(const Comp lex&oth 2er ){...},那么使用复数类声明两个对象Comp lex obj1,obj2;后,就可以直接使用obj1+obj2表示对

复数求和的操作,使得程序语言更接近习惯用法.C++语言中颇具典型的例子就是插入符“<<”和

提取符“>>”的重载.在C 语言中,利用库函数

p rintf ()输出或scanf ()输入时需要用参数指明输出或输入的数据类型方可正确输出或输入,而在C++

56

 广州航海高等专科学校学报第13卷 

中,由于在ostrea m类和istrea m类中大量重载了“< <”和“>>”,C++的内部数据类型编译器能自动判别并正确输入输出,使用起来变得非常方便.如: cout<<"x="<>”的操作,同样可以象上例那样方便地输入输出自定义的数据类型.

函数重载允许程序员用相同的名字定义两个或更多的C++函数,使得语义相似的函数可以用同样的标识符来命名,它是获得多态性的常用途径.例如对构造函数的重载,可使程序对类对象有多种不同的途径进行初始化.C语言不支持函数重载,每一个函数必须具有唯一的名字,不利于处理相似性问题.运用C++提供的函数重载机制,对解决相似问题的函数可使用相同的名字,即进行重载:

int abs(int x){...}

l ong abs(l ong x){...}

double abs(double x){...}

函数重载时使用的是静态绑定,编译程序在编译时根据实际参数的个数与相应位置的类型选择调用相关版本的重载函数.这种多态性尤其便利于大型的程序设计.但函数重载适宜在函数实现的语义非常相近时使用,同时应避免产生无法消解的二义性问题.

1.3 包含多态

在C++中,包含多态性是指相同的函数名出现在不同的类中,而且这样的函数必须是虚函数并以继承为基础的.使用包含多态性必须先设计一个类层次,在类中使用虚函数(这个类叫多态类),结合动态绑定实现[3].根据赋值兼容规则,公有派生类兼容基类,指向基类对象的指针变量可以指向其公有派生类的对象,这就意味着一个公共的消息集既可以被送到基类对象,也可以被送到其公有派生类的对象,那么就可以用一组相同的方法和逻辑来使用这个类层次中不同类中的同名虚函数,而虚函数中定义的具体操作可以是不同的,这是这种多态性的实质.以下是实例:

#include

classMe mber{ //成员基类

public:

virtual v oid showme(){cout<<"I a m a Me m2 ber.\n";return;}};

class Teacher:public Me mber{ //由成员类派生出的教师类

public:

 virtual void showme(){cout<<"I a m a Teacher.\n";return;}};

class Student:public Me mber{ //由成员类派生出的学生类

public:

 virtual void showme(){cout<<"I a m a Student.\n";return;}};

void main()

{Me mber me m;Teacher tch;Student std;

Me mber3who;

who=&me m;who->showme();

who=&tch;who->showme();

who=&std;who->showme()

return;};

运行结果为:

I a m a Me mber.

I a m a Teacher.

I a m a Student.

基类指针who分别指向基类对象和两个不同的派生类对象,运行期间将根据所指对象类型来动态绑定,决定调用哪一个类中定义的showme()虚函数版本.利用虚函数,可在基类和派生类中使用相同的函数名定义函数的不同实现,从而实现“一个接口,多种方式”.

当基类中无法给出虚函数的合理定义或软件设计需要构造更高层次的抽象时,可以利用C++提供的纯虚函数来设计包含多态性,含有纯虚函数的类叫抽象类.例如,设计一个多态数据结构,要能存放三角形、矩形、圆等多种图形数据,并提供计算相应图形面积的功能.可以抽取有关图形的共性设计一个基类F I G URE,用纯虚函数描述共同行为:计算面积,再派生出各种图形类给出具体实现方法,用堆栈存放指向图形对象的指针.基类层次如图1所示

.

图1 基类层次图

class F I G URE{...virtual double get_area()= 0;...};//基类中用纯虚函数表示求图形面积