C++程序设计与数据结构基础:第7章 多态性和虚函数

上传人:m**** 文档编号:569943967 上传时间:2024-07-31 格式:PPT 页数:27 大小:629.50KB
返回 下载 相关 举报
C++程序设计与数据结构基础:第7章 多态性和虚函数_第1页
第1页 / 共27页
C++程序设计与数据结构基础:第7章 多态性和虚函数_第2页
第2页 / 共27页
C++程序设计与数据结构基础:第7章 多态性和虚函数_第3页
第3页 / 共27页
C++程序设计与数据结构基础:第7章 多态性和虚函数_第4页
第4页 / 共27页
C++程序设计与数据结构基础:第7章 多态性和虚函数_第5页
第5页 / 共27页
点击查看更多>>
资源描述

《C++程序设计与数据结构基础:第7章 多态性和虚函数》由会员分享,可在线阅读,更多相关《C++程序设计与数据结构基础:第7章 多态性和虚函数(27页珍藏版)》请在金锄头文库上搜索。

1、第二部分第二部分 C+C+面向对象程序设计面向对象程序设计第七章 多态性与虚函数 本章内容本章内容 多态性概述多态性概述 运算符重载运算符重载 虚函数虚函数27.1多多态性概述性概述l多态性是面向对象程序设计的一个重要特征。l多态性(Polymorphism):是指发出同样的消息被不同类型的对象接收时而导致不同的行为。(所谓发消息就是调用类中的成员函数。)l多态性的分类:参数多态参数多态包含多态包含多态重载多态重载多态强制多态强制多态静态联编静态联编动态联编动态联编通用多态通用多态专用多态专用多态3说明:l强制多态(coercion):编译程序通过语义操作,把操作对象的类型强行加以变换,以符合

2、函数或操作符的要求。例如:3.143/2; 强制类型转换(int)3.14+2函数原型int f1(int); 函数调用 f1(3.14);l重载多态(overloading):同一个名(操作符函数名)在不同的上下文中有不同的类型。函数重载运算符重载int add(int x, int y)return x+y;double add(double x, double y)return x+y;coutadd(3, 4)endl;coutadd(3.4, 4.7)endl;4l参数多态( parametric ): 采用参数化模板,通过给出不同的类型参数,使得一个结构有多种类型。#include

3、 template /函数模板T add(T *x, int n)T s=0;for(int i=0;in;i+)s+=xi;return s;void main()int x=1, 2, 3, 4, 5;double y=1.1, 2.2, 3.3, 4.4, 5.5;cout整数相加结果:add(x, 5)n;cout实数相加结果:add(y, 5)n; 5class A int Buffer10; public: A() for(int k=0;k=0& i10) Bufferi=v; else cout=0 & i10) return Bufferi; else cout下标越界n;

4、return 0; class B double Buffer5; public: B() for(int k=0;k=0& i5) Bufferi=v; else cout=0 & i5) return Bufferi; else cout下标越界n; return 0; template/模板参数表class A double BufferN; public: A() for(int k=0; kN; k+) Bufferk=0; void SetElem(int i, T v); T GetElem(int i);templatevoid A:SetElem(int i, T v) if

5、(i=0& iN)Bufferi=v; else cout 下标越界n;templateT A:GetElem(int i) if (i=0 & iN)return Bufferi; else cout下标越界n; return 0; /模板实例化void main()A m;A x; A s;6l包含多态( inclusion ): 同样的操作可用于基类及其派生类。派生类中成员函数的重定义(覆盖,overwrite)虚函数l联编(binding,绑定)的概念:使计算机程序彼此关联的过程,将一个标识符和一个存储地址联系在一起的过程。静态联编( static binding,静态多态性):在编译

6、期间确定的多态性。主要包括重载多态和参数多态。动态联编( dynamic binding,动态多态性):在运行期间才能确定的多态性。主要包括包含多态和强制多态。7整数的加法:1+12实数的加法:1.6+2.64.2复数的加法:(1+2i)+(3+4i)=4+6i矢量的加法:n维线性空间的加法。l数学中的运算符重载现象 7.2 运算符重运算符重载8l一个例子# include class Aint x,y;public:A(int i=1,int j=2):x(i),y(j)void print()coutx=x,y=yendl;void main()A a(10,20), b(30,40),

7、c;c=a+b;c.print();A add(A m, A n)A k;k.x=m.x+n.x;k.y=m.y+n.y;return k;9# include class Aint x,y;public:A(int i=1,int j=2):x(i),y(j)void print()coutx=x,y=yendl;A add(A m, A n)A k;k.x=m.x+n.x;k.y=m.y+n.y;return k;void main()A a(10,20), b(30,40), c;c=add(a,b);c.print();# include class Aint x,y;public:A

8、(int i=1,int j=2):x(i),y(j)void print()coutx=x,y=yendl;friend A add(A, A);A add(A m, A n)A k; k.x=m.x+n.x;k.y=m.y+n.y;return k;void main()A a(10,20), b(30,40), c;c=add(a,b);c.print();A add(const A& m, const A& n) return A(m.x+n.x,m.y+n.y); friend A add(const A&, const A&);10# include class Aint x,y;

9、public:A(int i=1,int j=2):x(i),y(j)void print()coutx=x,y=yendl;A add(const A& r) return A(x+r.x,y+r.y); ;/*A add(A m, A n)A k; k.x=m.x+n.x;k.y=m.y+n.y;return k;*/void main()A a(10,20), b(30,40), c;c=a.add(b);c.print();11# include class Aint x,y;public:A(int i=1,int j=2):x(i),y(j)void print()coutx=x,

10、y=yendl;A operator+(const A& r) return A(x+r.x,y+r.y); ;void main()A a(10,20), b(30,40), c;c=a+b;/加法运算符加法运算符“+”的重载的重载c.print();12# include class Aint x,y;public:A(int i=1,int j=2):x(i),y(j)void print()coutx=x,y=yendl;friend A operator+(const A&, const A&);A operator+(const A& m, const A& n)return A(

11、m.x+n.x,m.y+n.y);void main()A a(10,20), b(30,40), c;c=a+b; /加法运算符加法运算符“+”的重载的重载c.print();13C+中的运算符重载l运算符重载的本质是一种特殊函数的重载C+将各种运算符都处理成一个函数调用。表达式“a+b”可以看成operator+(a, b) 或 a.operator+(b) l运算符重载函数的实现 可以利用成员运算符函数和友元运算符函数实现运算符的重载。14将运算符重载为类的成员函数l函数原型的格式class 类名 . 返回类型 operator 运算符(形参表); .;l类体外定义重载运算符函数返回类型

12、 类名:operator 运算符(形参表)15P191 例例7.1 利用成利用成员函数函数实现两个复数的加减二两个复数的加减二元运算。元运算。z1=x1+y1iz2=x2+y2iz3=z1z2=(x1x2)+(y1y2)i#include class complex private: double real, imag;public: complex(double r=0,double i=0)real=r;imag=i; complex operator+(const complex &a); void display();complex complex: operator+(const c

13、omplex &a) return complex(real+a.real,imag+a.imag);void complex:display() cout(real“+imagi)endl;main() complex c1(3,4), c2(5,-10), c3; c3=c1+c2; /相当于相当于c3=c1.operator+(c2); coutc1=;c1.display(); coutc2=;c2.display(); coutc1+c2=;c3.display();作业:作业:1.定义复数的减、乘、除运算符重载定义复数的减、乘、除运算符重载16将运算符重载为类的友元函数l函数原型的

14、格式class 类名 . friend 返回类型 operator 运算符(形参表); .;l类体外定义重载运算符函数返回类型 operator 运算符(形参表)17 利用友元函数利用友元函数实现两个复数的加减二两个复数的加减二元运算。元运算。z1=x1+y1iz2=x2+y2iz3=z1z2=(x1x2)+(y1y2)i#include class complex private: double real, imag;public: complex(double r=0,double i=0)real=r;imag=i; friend complex operator+(const comp

15、lex &a, const complex &b); void display();void complex:display() cout(real“+imagi)endl;complex operator+(const complex &a, const complex &b) return complex(a.real+b.real, a.imag+b.imag); main() complex c1(3,4), c2(5,-10), c3; c3=c1+c2; /相当于相当于c3=operator+(c1, c2); coutc1=;c1.display(); coutc2=;c2.di

16、splay(); cout”只能选择用成员函数;对于复合赋值运算符“+=、-=、/=、*=”等常常选择用成员函数。对于其他运算符,如“+、-、*、/”等常常选择用友元函数,以适应更多的计算形式19l例如,对于复数类对象相加来说, 用友元函数实现时,表达式4.5+c1可以正确计算,将被解释成operator+(complex(4.5),c1)。l而用成员函数实现时, 表达式4.5+c1将是一个错误的表达式,因为若将以上加法重载为成员函数时,表达式4.5+c1将被解释为4.5.operator+(c1),而4.5是一个基本类型的常数,不能自动转换为复数类对象。作业:作业:阅读阅读p194201例例

17、7.37.720重载运算符的规则l只能重载C+中已有的可重载的运算符,不能建立新的运算符;l重载运算符时不能改变原运算符操作数的个数、原有运算符的优先级和结合性,也不能改变原运算符对于内部基本类型对象的含义; l如果重载了某个运算符(如“=”),并不意味着重载了相关的运算符(如“+=”、“-=”等);l不可重载的运算符:“” 圆点运算符、“*” 成员指针选择运算符、“”域分辨运算符 、“?:” 条件运算符、“sizeof” 长度运算符。217.3 虚函数虚函数l引入虚函数的原因:P201例7.8#include const double PI=3.14159; class Point/定义基类

18、定义基类 public: Point(double i, double j)x=i;y=j; double Area()return 0.0; private: double x, y; /点坐标点坐标 ; class Circle: public Point double radius; /增加新成员增加新成员半径半径 public: Circle(double r, double i, double j) :Point(i,j),radius(r) double Area() return PI*radius*radius; void fun(Circle *p)coutArea()end

19、l; void main() Circle cir(10,3,6); fun(&cir);/面积为面积为314void fun(Point *p)coutArea()Area()指向谁?指向谁?由由赋值兼容性赋值兼容性原则,可以将原则,可以将派生类派生类的地址的地址赋值给指向其赋值给指向其基类的指针基类的指针变量。变量。此时,此时,该指针变量是指向了派生类对该指针变量是指向了派生类对象中所包含的基类的成员。象中所包含的基类的成员。22虚函数、动态联编、包含多态#include const double PI=3.14159; class Point public: Point(double i

20、, double j)x=i;y=j; virtual double Area()return 0.0; private: double x, y; /点坐标点坐标 ; class Circle: public Point double radius; /增加新成员增加新成员半径半径 public: Circle(double r, double i, double j) :Point(i,j),radius(r) virtual double Area() return PI*radius*radius; void fun(Point *p)coutArea()endl; void main

21、() Circle cir(10,3,6); fun(&cir);在在main()中定义指向根基类的中定义指向根基类的指针指针p可可以指向以指向派生类派生类对象对象。在执行过程中,可在执行过程中,可根据指针根据指针p的当前指的当前指向而调用相应类的虚函数向而调用相应类的虚函数,从而实现动态,从而实现动态的多态性的多态性。23虚函数使用的几个问题l虚函数是一种成员函数,而且是非static的成员函数。一个函数被说明或定义为虚函数后,表示它在派生类中可能有多种不同的实现,即重新定义。l格式:virtual 类型名 函数名(形参表) 函数体 l在派生类中重新定义时,其函数原型,包括返回类型、函数名、

22、参数个数和类型以及各参数顺序,都必须与基类中的原型完全相同。否则,将处理为静态联编。l各派生类中重定义的虚函数仍是虚函数,可以不加关键字virtual而由系统自动判断。l虚函数只能通过指针或引用所表示的对象来调用。24l构造函数不允许为虚函数,但析构函数允许为虚函数,以便能自动释放由指针或引用所表示的对象。虚析构函数的格式: virtual 类名()虚析构函数体 如果一个类的析构函数为虚函数,则由它派生而来的所有派生类的析构函数均为虚析构函数#include class A public: A( int m=0) x=m; virtual A()cout类类A虚析构函数虚析构函数n; priv

23、ate: int x; class B:public A public: B(int n,int m):A(m) size=n; buf=new charn; B()deletebuf; cout类类B虚析构函数虚析构函数n; private: char *buf; int size; ; void fun(A *a) delete a; void main() A *a=new B(10,7); fun(a); 程序输出结果程序输出结果: 类类B虚析构函数虚析构函数 类类A虚析构函数虚析构函数; 25纯虚函数与抽象类l如果无法为基类的虚函数提供一个实现版本,可将之说明为纯虚函数。l形式为:v

24、irtual 类型名 函数名(形参表)=0; l有纯虚函数的类称为抽象类,抽象类只能作为其它类的基类(即根基类)使用,不能定义抽象类的对象,但是可以定义抽象类的指针或引用,以便用这些指针和引用实现多态性。l抽象类不能作为函数返回类型、参数类型,也不能作为转换结果的类型。l继承抽象类纯虚函数的派生类仍是一个抽象类,只有在派生类 中给出基类纯虚函数的实现时,该派生类才可以建立对象。26P205 例7.11纯虚函数和抽象类的使用#include const double PI=3.1415926; class shape /抽象类定义抽象类定义 public: virtual void PrintS

25、hapeName()=0; virtual double Area()=0; virtual double Volume()=0; ; class Point: public shape /定义点类定义点类 public: Point(double a=0,double b=0) x=a;y=b; double GetX() return x; double GetY() return y; virtual double Area()return 0.0; virtual double Volume()return 0.0; virtual void PrintShapeName()cout0

26、?r:0; /初始化为安全的值初始化为安全的值 double Getradius()return radius; double Area()return PI*radius*radius; double Volume()return 0.0; virtual void PrintShapeName()cout圆圆:; private: double radius; ; class Sphere :public Circle/定义球体类定义球体类 public: Sphere(double r=0.0,double a=0.0,double b=0.0) :Circle(r,a,b) /球体没有

27、特殊的数据成员球体没有特殊的数据成员 virtual void PrintShapeName()coutPrintShapeName(); coutx=p2.GetX(), ; couty=p2.GetY (), ; cout面积面积=Area (), ; cout体积体积=Volume()endl; void main() Point point(7,11); print(&point, point); Circle circle(10,8,32); print(&circle,circle); Sphere sphere(10,20,8); print(&sphere,sphere); shape(抽象类抽象类)Point(图元类图元类)Circle(平面图形类平面图形类)Sphere(立体图形类立体图形类)程序输出结果程序输出结果: 点点:x=7,y=11,面积面积=0,体积体积=0 圆圆:x=8,y=32,面积面积=314.159,体积体积=0 球体球体:x=20,y=8,面积面积=1256.64,体积体积=4188.79 讨论:如果没有虚函数的机制会怎么样?讨论:如果没有虚函数的机制会怎么样?27

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

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