四章多态.ppt

上传人:本田雅阁 文档编号:3194253 上传时间:2019-07-29 格式:PPT 页数:48 大小:121.01KB
返回 下载 相关 举报
四章多态.ppt_第1页
第1页 / 共48页
四章多态.ppt_第2页
第2页 / 共48页
四章多态.ppt_第3页
第3页 / 共48页
四章多态.ppt_第4页
第4页 / 共48页
四章多态.ppt_第5页
第5页 / 共48页
点击查看更多>>
资源描述

《四章多态.ppt》由会员分享,可在线阅读,更多相关《四章多态.ppt(48页珍藏版)》请在三一文库上搜索。

1、1,第四章 多态性,C+程序设计,2,本章主要内容,多态性概念 运算符重载 虚函数 纯虚函数 抽象类(虚基类),3,多态性的概念,多态性是指发出同样的消息被不同类型的对象接收时导致完全不同的行为,是面向对象程序设计的重要特征之一。 多态的实现: 函数重载 运算符重载 虚函数,4,4.1 函数重载,基类和派生类中的函数重载有两种情况: 1.参数或返回值有所差别的重载。 2.函数的参数完全相同,只是属于不同的类, 可使用“对象名” 或使用“类名:”加以区分。,5,例,class point int x,y; public: point(int a,int b) x=a;y=b; float are

2、a() return 0; ;,class circle:public point int radius; public: circle(int x,int y,int rad):point(x,y) radius=rad; float area() return 3.1416*radius*radius; ;,6,main( ) point p(20,20); circle c(8,8,30); coutp.area()endl; coutc.area()endl; coutc.point:area()endl; ,结果: 0 2827.439941 0,/用对象名加以区分 /用类名加以区分

3、,7,4.2 运算符重载,class complex /复数类声明 public: complex(double r=0.0,double i=0.0)real=r;imag=i; /构造函数 void display(); /显示复数的值 private: double real; double imag; ;,问题举例复数的运算,8,问题举例复数的运算,问题:用“+”、“-”能够实现复数的加减运算吗?,实现复数加减运算的方法 重载“+”、“-”运算符,9,1. 运算符重载基本阐述,1)运算符重载是对已有的运算符赋予多重含义 2)必要性 C+中预定义的运算符其运算对象只能是基本数据类型,而不

4、适用于用户自定义类型(如类) 3)实现机制 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。 编译系统对重载运算符的选择,遵循函数重载的选择原则。,10,2.规则和限制,可以重载C+中除下列运算符外的所有运算符: . (类属关系运算符) .* (成员指针运算符) : (作用域分辨符) ?:(三目运算符) 只能重载C+语言中已有的运算符。 不改变原运算符的优先级和结合性。 不能改变操作对象个数。 经重载的运算符,其操作对象中至少应该有一个是自定义类型。,11,3.运算符重载形式,重载为类的非静态成员函数。 重载为非成员函数。当以非成员函数形式重载运算符时,有时需要访问

5、运算符参数所涉及类的私有成员,这时应将该函数声明为类的友元函数,12,4. 运算符函数,定义形式 返回类型 operator 运算符(形参表) 函数体 重载为类成员函数时 参数个数=原操作数个数-1 (后置+、-除外) 重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。,13,5. 运算符成员函数的设计1,双目运算符 B 如果要重载 B 为类成员函数,使之能够实现表达式 oprd1 B oprd2,其中 oprd1 为A 类对象,则 B 应被重载为 A 类的成员函数,形参类型应该是 oprd2 所属的类型。 经重载后,表达式 oprd1 B oprd2 相当于 opr

6、d1.operator B(oprd2) * 第一个操作数被作为函数调用的目的对象,因此无须出现在参数表中,14,例4.1,将“+”、“-”运算重载为复数类的成员函数。 规则: 实部和虚部分别相加减。 操作数: 两个操作数都是复数类的对象。,class complex /复数类声明 public: /外部接口 complex(double r =0.0,double i=0.0) real=r;imag=i; /构造函数 complex operator + (complex c2); /+重载为成员函数 complex operator - (complex c2); /-重载为成员函数 v

7、oid display( ); /输出复数 private: /私有数据成员 double real; /复数实部 double imag; /复数虚部 ;,complex complex:operator +(complex c2) /重载函数实现 complex c; c.real=c2.real+real; c.imag=c2.imag+imag; return complex(c.real,c.imag); /return c; ,complex complex:operator -(complex c2) /重载函数实现 complex c; c.real=real-c2.real;

8、 c.imag=imag-c2.imag; return complex(c.real,c.imag); /return c; ,void complex:display() cout“(“real“,“imag“)“endl; void main() /主函数 complex c1(5,4),c2(2,10),c3; /声明复数类的对象 cout“c1=“;c1.display(); cout“c2=“;c2.display(); c3=c1-c2; /使用重载运算符完成复数减法 cout“c3=c1-c2=“; c3.display(); c3=c1+c2; /c1.operator+(c

9、2) cout“c3=c1+c2=“; c3.display(); ,程序输出的结果为: c1=(5,4) c2=(2,10) c3=c1-c2=(3,-6) c3=c1+c2=(7,14),19,5. 运算符成员函数的设计2,前置单目运算符 U(以前置+与-为例) 如果要重载 +为类成员函数,使之能够实现表达式 +oprd,其中 oprd 为A类对象,则 + 应被重载为 A 类的成员函数,无形参。 经重载后, 表达式 + oprd 相当于 oprd.operator +(),20,5.运算符成员函数的设计3,后置单目运算符 +和- 如果要重载 +或-为类成员函数,使之能够实现表达式 oprd

10、+ 或 oprd- ,其中 oprd 为A类对象,则 +或- 应被重载为 A 类的成员函数,且具有一个 int 类型形参。 经重载后,表达式 oprd+ 相当于 oprd.operator +(),21,例4-3,将运算符前置+和后置+重载为时钟类的成员函数。 (1)前置单目运算符,重载函数没有形参,对于后置单目运算符,重载函数需要有一个整型形参。 (2)操作数是时钟类的对象。 (3)实现时间增加1秒钟。,#include class Clock /时钟类声明 例4-2 public: /外部接口 Clock(int NewH=0, int NewM=0, int NewS=0) Hour=N

11、ewH; Minute=NewM; Second=NewS; void ShowTime(); void operator +(); /前置单目运算符重载 void operator +(int); /后置单目运算符重载 private: /私有数据成员 int Hour, Minute, Second; ;,void Clock:operator +() /前置单目运算符重载函数 +Second; if(Second=60) Second=Second-60; Minute+; if(Minute=60) Minute=Minute-60; Hour+; Hour=Hour%24; cout

12、“+Clock: “; ,void Clock:operator +(int) /后置单目运算符重载 if(Second=60) Second=Second+-60; Minute+; if(Minute=60) Minute=Minute-60; Hour+; Hour=Hour%24; cout“Clock+: “; ,void Clock:ShowTime() coutHour“:“Minute“:“Secondendl; void main() Clock myClock(23,59,59); cout“First time output:“; myClock.ShowTime();

13、myClock+; myClock.ShowTime(); +myClock; myClock.ShowTime(); ,程序运行结果为: First time output:23:59:59 Clock+: 23:59:59 +Clock: 0:0:0,27,6.友元运算符函数,如果需要重载一个运算符,使之能够用于操作某类对象的私有成员,可以此将运算符重载为该类的友元函数。 函数的形参代表依自左至右的次序排列各操作数。 后置单目运算符 +和-的重载函数,形参列表中要增加一个int,但不必写形参名。,28,7.运算符友元函数的设计,双目运算符 B重载后, 表达式oprd1 B oprd2 等同

14、于operator B(oprd1,oprd2 ),29,例4.3,将+、-(双目)重载为复数类的友元函数。 两个操作数都是复数类的对象。,class complex /复数类声明 public: /外部接口 complex(double r=0.0,double i=0.0) real=r; imag=i; /构造函数 friend complex operator + (complex c1,complex c2); /运算符+重载为友元函数 friend complex operator - (complex c1,complex c2); /运算符-重载为友元函数 void displ

15、ay(); /显示复数的值 private: /私有数据成员 double real; double imag; ;,complex operator +(complex c1,complex c2) /运算符重载友元函数实现 return complex(c2.real+c1.real, 2.imag+c1.imag); complex operator -(complex c1,complex c2) /运算符重载友元函数实现 return complex(c1.real-c2.real, c1.imag-c2.imag); / 其它函数和主函数同例1,32,4.3 静态联编与动态联编,联

16、编 程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系。 静态联编 联编工作出现在编译阶段,用对象名或者类名来限定要调用的函数。 动态联编 联编工作在程序运行时执行,在程序运行时才确定将要调用的函数。,33,静态联编例1,class point float x,y; public: void setIcon(float I,float j)x=i;y=j; float area() return 0; ; const float pi=3.1415; class circle:public point float radius; public: void setSize(f

17、loat r)radius=r; float area()return pi*radius*radius; /重载 ;,34,void main() point *pp; circle c; c.setSize(3.6); pp= ,静态联编例1,35,class Point public: Point(double i, double j) x=i; y=j; double Area() const return 0.0; private: double x, y; ; class Rectangle:public Point public: Rectangle(double i, doub

18、le j, double k, double l); double Area() const return w*h; private: double w,h; ;,静态联编例2,36,Rectangle:Rectangle(double i, double j, double k, double l) :Point(i, j) w=k; h=l; void fun(Point 运行结果:Area=0,静态联编例2,37,1. 虚函数,虚函数是动态联编的基础,体现了运行中的多态性。 是非静态的成员函数。 在类的定义中,在函数原型之前写virtual。 具有继承性,基类中定义了虚函数,派生类中无论

19、是否说明,同原型函数都自动为虚函数。 本质:不是重载定义而是覆盖定义。 调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。,38,虚函数例,#include class B0 /基类B0声明 public: /外部接口 virtual void display() cout“B0:display()“endl; /虚成员函数 ;,39,class B1: public B0 /公有派生 public: void display() cout“B1:display()“endl; ; class D1: public B1 /公有派生 public: void di

20、splay() cout“D1:display()“endl; ;,虚函数例,40,void fun(B0 *ptr) /普通函数 ptr-display( ); void main( ) B0 b0, *p; /声明基类对象和指针 B1 b1; /声明派生类对象 D1 d1; /声明派生类对象 p= /调用派生类D1函数成员 ,虚函数例,程序的运行结果为: B0:display() B1:display() D1:display(),41,虚函数,运行中的多态要满足三个条件 1)类之间要满足类型兼容原则 2)声明虚函数 3)由成员函数来调用或者是通过指针、引 用来访问虚函数。,42,虚函数,

21、上面的例子中,派生类并没有显式给出虚函数声明,这时系统会遵循以下原则来判断派生类的一个函数成员是不是虚函数。 该函数是否与基类的虚函数有相同的名称。 该函数是否与基类的虚函数有相同的参数个数与参数类型 该函数是否与基类的虚函数有相同的返回值或者满足类型兼容原则的指针、引用型的返回值。 如果满足了上述条件,就会自动定义为虚函数。此时,派生类的虚函数便覆盖了基类的虚函数。,43,2. 抽象类的一般形式,带有纯虚函数的类称为抽象类: 抽象类定义: class 类名 virtual 函数类型 函数名(参数表)=0; /纯虚函数,声明为纯虚函数后,基类中就可以不再给出函数的实现部分。纯虚函数的函数体由派

22、生类给出。 . ,44,3. 作用,抽象类为抽象和设计的目的而建立,通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。而接口的完整实现,即纯虚函数的函数体,要由派生类自己定义。 对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。,45,注意,抽象类只能作为基类来使用。 不能定义抽象类的对象,即不能实例化。 构造函数不能是虚函数,析构函数可以是 虚函数。,46,本章小结,多态 同样的消息被不同类型的对象接收时导致完全不同的行为。 运算符重载 对已有的运算符赋予多重含义,使用已有运算符对用户自定义类型(比如类)进行运算操作。,47,本章小结,联编 程序自身彼此关联的过程称为联编,联编确定程序中的操作调用与执行该操作的代码间的关系。 静态联编工作出现在编译阶段。 动态联编工作在程序运行时执行。 虚函数是动态联编的基础。,48,本章小结,纯虚函数 在基类中说明的虚函数,它在该基类中没有定义函数体,要求各派生类根据实际需要定义自己的函数体。 抽象类 带有纯虚函数的类是抽象类。 抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效地发挥多态特性。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1