c++程序设计_04章+多态性

上传人:xh****66 文档编号:61653179 上传时间:2018-12-08 格式:PPT 页数:28 大小:56.50KB
返回 下载 相关 举报
c++程序设计_04章+多态性_第1页
第1页 / 共28页
c++程序设计_04章+多态性_第2页
第2页 / 共28页
c++程序设计_04章+多态性_第3页
第3页 / 共28页
c++程序设计_04章+多态性_第4页
第4页 / 共28页
c++程序设计_04章+多态性_第5页
第5页 / 共28页
点击查看更多>>
资源描述

《c++程序设计_04章+多态性》由会员分享,可在线阅读,更多相关《c++程序设计_04章+多态性(28页珍藏版)》请在金锄头文库上搜索。

1、,第4章 多态性,4.1 多态性概述 多态性的概念:(polymorphisn) 是指多种表现形式,具体地说,就是把同样的消息发给不同类型的对象后可能导致完全不同的行为,即“一个对外接口,对应多个内在实现方法”。多态性连同前面所讲过的封装性和继承性一起,构成了面向对象程序设计的三大基本特征。 多态性的实现: 函数重载 运算符重载 虚函数 从系统实现角度来看,多态性包括静态多态性(编译时多态性)和动态多态性(运行时多态性)两大类。 静态多态性:是通过函数重载和类属机制来实现的。在程序编译时系统就能确定调用哪个函数,因此静态函数又称编译时的多态性。例如:函数重载和运算符重载就属于这种情况。 动态多

2、态性:是通过虚函数、继承机制,以及动态绑定机制来实现的。在程序运行过程中才动态地确定操作指针所指的对象,主要通过虚函数和重写来实现。,4.2 运算符重载,4.2.1 运算符重载的概念 运算符重载:是指将同一个运算符作用于不同的运算对象时,可以实现不同的操作。其意义在于,使程序的表达方式更加符合人们平时的表达习惯,易于接受。 运算符具有函数的特性,我们可以将一个运算符看成是一个函数名,我们使用一个运算符,就相当于是在调用一个函数。比如:3+2可以理解成+(3,2),即调用函数+,并给出两个实参3和2。 为此,运算符重载和函数重载本质上就是相同的。 4.2.2 运算符重载的规则 1、有5种运算符不

3、能重载,它们是类属关系运算符“.”,成员指针运算符“*”,作用域分辨符“:”,sizeof运算符和条件运算符“?:”。 2、重载后的运算符有四个“不能改变”:不能改变运算符原有的优先级;不能改变运算符原有的结合性;不能改变运算符原有的语法结构;不能改变运算符操作数的个数。 3、至少要有一个操作对象是自定义类型,否则就不必重载了。,4.2.3 运算符重载的语法 返回类型 类名:operator 操作符(形参表) 4.2.4 运算符重载的方法 1、用类成员函数实现运算符重载:其中=、 、( )、-等运算符必须采用这种方法实现重载。 用类成员函数实现重载时,参数个数=原操作数个数-1(后置+、-除外

4、)。 比如:要重载一个双目运算符P为类成员函数,使之能够实现表达式 oprd1 P oprd2的运算,其中 假定oprd1 为A 类的对象,则P就应该被重载为 A 类的成员函数,形参类型应该是oprd2所属的类型。经重载后,执行表达式 oprd1 P oprd2就相当于是执行oprd1.operatorP(oprd2)。,又如:要重载前置单目运算符P为类成员函数,使之能够实现表达式P oprd的运算,其中假定oprd 为A类的对象,则P就应该被重载为 A 类的成员函数,没有形参。经重载后,执行表达式P oprd就相当于执行oprd.operatorU( ) 。 再如:要重载后置单目运算符P(+

5、或-)为类成员函数,使之能够实现表达式 oprd P,其中假定oprd 为A类的对象,则P就应该被重载为 A 类的成员函数,且具有一个int类型的形参。经重载后,执行表达式oprd P就相当于执行oprd.operator P(0) 。这里的参数个数与重载前置单目运算符时不相同,以此区分前置的P。,4.2.5 运算符重载的例子,例1 请用类成员函数重载“+”、“-”两个双目运算符,使之可以用于复数的运算。 #include using namespace std;/可用#include来替换这两行 class complex /复数类声明 public: /外部接口 complex(doubl

6、e r=0.0,double i=0.0) real=r;imag=i; complex operator+ (complex c2); /+重载为成员函数 complex operator- (complex c2); /-重载为成员函数 void display(); /输出复数 private: /私有数据成员,自己内部使用 double real; /复数实部 double imag; /复数虚部 ;,complex complex:operator+(complex c2) complex c; c.real=c2.real+real; c.imag=c2.imag+imag; re

7、turn complex(c.real,c.imag); complex complex:operator-(complex c2) complex c; c.real=real-c2.real; c.imag=imag-c2.imag; return complex(c.real,c.imag); void complex:display() coutreal“+(“imag“)i“endl; ,void main() complex c1(2,3),c2(6,8),c3; /声明复数类的对象 cout“c1=“; c1.display(); cout“c2=“; c2.display();

8、 c3=c1-c2; /使用重载运算符完成复数减法 cout“c3=c1-c2=“; c3.display(); c3=c1+c2; /使用重载运算符完成复数加法 cout“c3=c1+c2=“; c3.display(); 运行结果: c1=2+(3)i c2=6+(8)i c3=c1-c2=-4+(-5)i c3=c1+c2=8+(11)i,例2 请用类成员函数分别重载单目运算符“+” 的前置和后置用法,使之可以用于时间的运算,不断地增加1秒。 #include using namespace std; class Clock /定义一个时钟类 public: Clock(int NewH

9、=0, int NewM=0, int NewS=0); void ShowTime(); Clock,Clock /将这个被前置运算后的对象通过引用返回 ,Clock Clock:operator +(int) /后置单目运算符重载函数 /注意形参表中的这个int参数,可以不写形参名,写了也不用 Clock old=*this; +(*this); /调用前置单目运算符重载函数 return old; /其它成员函数的实现 Clock:Clock(int NewH, int NewM, int NewS) Hour=NewH; Minute=NewM; Second=NewS; void C

10、lock:ShowTime() coutHour“:“Minute“:“Secondendl; ,void main() Clock myClock(23,59,59); cout“Time:“; myClock.ShowTime(); cout“Show +Time:“; (+myClock).ShowTime(); cout“Show Time+:“; (myClock+).ShowTime(); 运行结果: Time:23:59:59 Show +Time:0:0:0 Show Time+:0:0:0,2、用友元函数实现运算符重载。 友元概念的引入: 按照封装性的概念,一个类之外的函数只

11、能访问这个类中的public成员。如果要让这个类之外的函数访问到自己的private或protected成员,就必须打破原有的封装性,方法就是设定该类的友元。应该说,友元和封装是一对相反的概念,一个是要“实现开放”,另一个则是要“限制开放”。 一个类的友元可以是一个普通的函数(即非成员函数)、另一个类的成员函数或者另一个完整的类。 如何设置一个类的友元呢?在类的定义中使用friend保留字进行说明,并在friend之后列出友元的名字。如果是把一个完整的类B作为类A的友元,则类B中所有的成员函数都将被视为类A的友元函数。,用友元函数实现重载时,参数个数=原操作数个数,且至少应该有一个自定义类型的

12、形参。 双目运算符 P重载后,表达式oprd1 P oprd2 等同于operatorP(oprd1,oprd2 ) 前置单目运算符P重载后,表达式 P oprd 等同于operatorP(oprd ) 后置单目运算符 P重载后,表达式 oprd P 等同于operatorP(oprd,0 ) 例3 请用友元函数重载“+”、“-”两个双目运算符,使之可以用于复数的运算。,#include using namespace std; class complex public: complex(double r=0.0,double i=0.0) real=r; imag=i; friend com

13、plex operator+ (complex c1,complex c2); /运算符+被重载为本类的友元函数 friend complex operator- (complex c1,complex c2); /运算符-被重载为本类的友元函数 void display(); /显示复数的值 private: /私有数据成员 double real; double imag; ;,complex operator+(complex c1,complex c2) /友元函数实现运算符重载 return complex(c2.real+c1.real, c2.imag+c1.imag); com

14、plex operator-(complex c1,complex c2) /友元函数实现运算符重载 return complex(c1.real-c2.real, c1.imag-c2.imag); / 其他函数和主函数同例1 注意:这里的operator+和operator-是两个普通函数(非成员函数)。 两种重载方法的比较: 一般说来,单目运算符最好被重载为成员函数;对双目运算符最好被重载为友元函数,双目运算符重载为友元函数比重载为成员函数更方便,但是,有的双目运算符还是重载为成员函数为好,例如,赋值运算符。因为,它如果被重载为友元函数,将会出现与赋值语义不一致的地方。,4.3 用虚函数

15、实现多态性,4.3.1 绑定方式 绑定(binding):是指对于具有多种解释的名字,将名字与它的某个含义相关联的过程。对于函数而言,就是将函数调用与某个函数体对应起来。 根据进行关联的时机不同,可将绑定分为早期绑定(又称静态绑定)和晚期绑定(又称动态绑定)。 静态绑定:绑定过程出现在编译阶段,在编译时就用对象名或者类名来限定要调用的函数。 动态绑定:绑定过程出现在运行阶段,在程序运行时才确定将要调用的函数。 在C+中,函数调用的默认绑定方式是静态绑定,只有通过基类类型的引用或指针调用被指定为虚函数的成员函数时才进行动态绑定,实现运行时多态性。 为此,可以看出,运行时多态性是通过虚函数、继承机

16、制,以及动态绑定机制来实现的。要实现运行时多态性必须同时满足下面4个条件:,要有一个继承层次; 在基类中要定义虚函数; 在公有派生类中要对基类中定义的虚函数进行重定义; 要通过基类指针(或基类引用)来调用虚函数。 4.3.2 虚函数 虚函数:是指在类定义体中使用保留字virtual来声明的成员函数。这个含有虚函数的类,称为多态类。 注意: 1、virtual 只能用在类的声明中、函数原型之前,不能用在函数实现时。 2、派生类对基类中的虚函数进行重定义,既不是要实现重载也不是要实现隐藏,而是要实现覆盖。 例4 一个静态绑定的例子,#include using namespace std; class Point public: Point(double i, double j) x=i; y=j;

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号