《第7章多态性和虚函数.ppt》由会员分享,可在线阅读,更多相关《第7章多态性和虚函数.ppt(24页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第7章多态性和虚函数现在学习的是第1页,共24页本章内容本章内容 多态性概述多态性概述 运算符重载运算符重载 虚函数虚函数现在学习的是第2页,共24页7.1多多态性概述性概述l多态性是面向对象程序设计的一个重要特征。l多态性(Polymorphism):是指发出同样的消息被不同类型的对象接收时而导致不同的行为。(所谓发消息就是调用类中的成员函数。)l多态性的分类:参数多态参数多态包含多态包含多态重载多态重载多态强制多态强制多态静态联编静态联编动态联编动态联编通用多态通用多态专用多态专用多态现在学习的是第3页,共24页说明: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;现在学习的是第4页,共24页l参数多态(parametric):采用参数化模板,通过给出不同的类型参数,使得一个结构有
3、多种类型。#include 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;现在学习的是第5页,共24页class 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(i=0&iN)Bufferi=v;else
5、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;现在学习的是第6页,共24页l包含多态(inclusion):同样的操作可用于基类及其派生类。派生类中成员函数的重定义(覆盖,overwrite)虚函数l联编(binding,绑定)的概念:使计算机程序彼此关联的过程,将一个标识符和一个存储地址联系在一起的过程。静态联编(static binding,静态多态性):在编译期间确定的多态性。主要包括重载多态和参数多态。动
6、态联编(dynamic binding,动态多态性):在运行期间才能确定的多态性。主要包括包含多态和强制多态。现在学习的是第7页,共24页整数的加法:1+12实数的加法:1.6+2.64.2复数的加法:(1+2i)+(3+4i)=4+6i矢量的加法:n维线性空间的加法。数学中的运算符重载现象 7.2 运算符重载运算符重载现在学习的是第8页,共24页l一个例子#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),c;
7、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页,共24页#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;pub
8、lic:A(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页,共24页#include class Ain
9、t x,y;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页,共24页#include class Aint x,y;public:A(int i=1,int j=2):x(i),y(j)void print
10、()coutx=x,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页,共24页#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
11、&n)return A(m.x+n.x,m.y+n.y);void main()A a(10,20),b(30,40),c;c=a+b;/加法运算符加法运算符“+”的重载的重载c.print();现在学习的是第13页,共24页C+中的运算符重载l运算符重载的本质是一种特殊函数的重载C+将各种运算符都处理成一个函数调用。表达式“a+b”可以看成operator+(a,b)或 a.operator+(b)l运算符重载函数的实现 可以利用成员运算符函数和友元运算符函数实现运算符的重载。现在学习的是第14页,共24页将运算符重载为类的成员函数l函数原型的格式class 类名 .返回类型 operato
12、r 运算符(形参表);.;l类体外定义重载运算符函数返回类型 类名:operator 运算符(形参表)现在学习的是第15页,共24页P191例例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(
13、);complex complex:operator+(const complex&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.定义复数的减、乘、除运算符重载定义复数的减、乘、除运算
14、符重载现在学习的是第16页,共24页将运算符重载为类的友元函数l函数原型的格式class 类名 .friend 返回类型 operator 运算符(形参表);.;l类体外定义重载运算符函数返回类型 operator 运算符(形参表)现在学习的是第17页,共24页 利用友元函数利用友元函数实现两个复数的加减二元运两个复数的加减二元运算。算。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=
15、r;imag=i;friend complex operator+(const complex&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=;c
16、1.display();coutc2=;c2.display();cout”只能选择用成员函数;对于复合赋值运算符“+=、-=、/=、*=”等常常选择用成员函数。对于其他运算符,如“+、-、*、/”等常常选择用友元函数,以适应更多的计算形式现在学习的是第19页,共24页l例如,对于复数类对象相加来说,用友元函数实现时,表达式4.5+c1可以正确计算,将被解释成operator+(complex(4.5),c1)。l而用成员函数实现时,表达式4.5+c1将是一个错误的表达式,因为若将以上加法重载为成员函数时,表达式4.5+c1将被解释为4.5.operator+(c1),而4.5是一个基本类型的
17、常数,不能自动转换为复数类对象。作业:作业:阅读阅读p194201例例7.37.7现在学习的是第20页,共24页重载运算符的规则l只能重载C+中已有的可重载的运算符,不能建立新的运算符;l重载运算符时不能改变原运算符操作数的个数、原有运算符的优先级和结合性,也不能改变原运算符对于内部基本类型对象的含义;l如果重载了某个运算符(如“=”),并不意味着重载了相关的运算符(如“+=”、“-=”等);l不可重载的运算符:“”圆点运算符、“*”成员指针选择运算符、“”域分辨运算符、“?:”条件运算符、“sizeof”长度运算符。现在学习的是第21页,共24页7.3 虚函数虚函数l引入虚函数的原因:P20
18、1例7.8#include const double PI=3.14159;class Point/定义基类定义基类 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*rad
19、ius;void fun(Circle*p)coutArea()endl;void main()Circle cir(10,3,6);fun(&cir);/面积为面积为314void fun(Point*p)coutArea()Area()指向谁?指向谁?由由赋值兼容性赋值兼容性原则,可以将原则,可以将派生类的派生类的地址地址赋值给指向其赋值给指向其基类的指针基类的指针变量。此时,变量。此时,该指针变量是指向了派生类对象中所包含的该指针变量是指向了派生类对象中所包含的基类的成员。基类的成员。现在学习的是第22页,共24页虚函数、动态联编、包含多态#include const double PI
20、=3.14159;class Point public:Point(double i,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)c
21、outArea()endl;void main()Circle cir(10,3,6);fun(&cir);在在main()中定义指向根基类的中定义指向根基类的指针指针p可以指可以指向向派生类派生类对象对象。在执行过程中,可在执行过程中,可根据指针根据指针p的当前指向而的当前指向而调用相应类的虚函数调用相应类的虚函数,从而实现动态的多态性,从而实现动态的多态性。现在学习的是第23页,共24页虚函数使用的几个问题l虚函数是一种成员函数,而且是非static的成员函数。一个函数被说明或定义为虚函数后,表示它在派生类中可能有多种不同的实现,即重新定义。l格式:virtual 类型名 函数名(形参表)函数体 l在派生类中重新定义时,其函数原型,包括返回类型、函数名、参数个数和类型以及各参数顺序,都必须与基类中的原型完全相同。否则,将处理为静态联编。l各派生类中重定义的虚函数仍是虚函数,可以不加关键字virtual而由系统自动判断。l虚函数只能通过指针或引用所表示的对象来调用。现在学习的是第24页,共24页