结合学习改进教学_第1页
结合学习改进教学_第2页
结合学习改进教学_第3页
结合学习改进教学_第4页
结合学习改进教学_第5页
已阅读5页,还剩44页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第8章 多态性,面向对象程序设计,本章主要内容,多态性运算符重载虚函数纯虚函数和抽象类,2,8.1 多态性概述,多态性的概念,多态性是面向对象程序设计的重要特征之一多态性是指:发出同样的消息,被不同类型的对象接收时,导致完全不同的行为。消息主要指对类的成员函数的调用。多态的实现:函数重载运算符重载虚函数,静态:编译时的多态, 动态:运行时的多态,3,8.1 多态性概述,绑定(binding),绑定(binding):是指计算机程序自身彼此关联的过程,也就是把一个标识符名和一个存储地址联系在一起的过程,就是把一条消息和一个对象的方法相结合的过程。静态绑定(static binding):绑定工作在编译连接阶段完成。如:重载、强制和参数多态动态绑定/晚期绑定(dynamic binding / late binding): 绑定在程序运行阶段完成!,4,8.1 多态性概述,本章主要内容,多态性运算符重载虚函数纯虚函数和抽象类,5,8.2 运算符重载,class Complex/复数类声明public:Complex(double r = 0.0, double i = 0.0):real(r), imag(i) /构造函数void display();/显示复数的值private:double real;double imag;,问题举例复数的运算,运算符重载,6,8.2 运算符重载,问题举例复数的运算,用“+”、“-”能够实现复数的加减运算吗?实现复数加减运算的方法 重载“+”、“-”运算符,7,8.2 运算符重载,运算符重载的实质,运算符重载:对已有的运算符赋予多重含义必要性C+中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)实现机制将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。编译系统对重载运算符的选择,遵循函数重载的选择原则。实质:只是一种“语法上的方便”,即:只是另外一种函数的调用形式。,8,8.2 运算符重载,规则和限制,可以重载C+中除下列运算符外的所有运算符: . .* : ?:只能重载C+语言中已有的运算符,不可臆造新的。不改变原运算符的优先级和结合性。不能改变操作数个数。经重载的运算符,其操作数中至少应该有一个是自定义类型。,9,8.2.1 运算符重载的规则,两种形式,重载为类成员函数。重载为非成员函数(为了访问类中的私有变量,一般可以声明为类的友元函数)。,10,8.2.1 运算符重载的规则,语法形式,声明形式重载为类成员函数时 参数个数 = 原操作数个数 - 1(后置+、-除外)重载为非成员函数时 参数个数 = 原操作数个数且至少应该有一个自定义类型的形参。,11,返回类型 operator 运算符(形参) .,例:Complex operator + (const Complex ,8.2.1 运算符重载的规则,运算符成员函数的设计,双目运算符 B如果要重载 B 为类成员函数,使之能够实现表达式: oprd1 B oprd2 (例如:m+n) 其中:oprd1 为A 类对象,则 B 应被重载为 A 类的成员函数,形参类型应该是 oprd2 所属的类型。经重载后,表达式 oprd1 B oprd2 相当于 oprd1.operator B(oprd2),12,8.2.2 运算符重载为成员函数,例 8.1,将“+”、“-”运算重载为复数类的成员函数。 规则:实部和虚部分别相加减。 操作数:两个操作数都是复数类的对象。,13,8_1,8.2.2 运算符重载为成员函数,#includeusing namespace std;class Complex/复数类声明public:Complex(double r=0.0,double i=0.0) : real(r), imag(i) /构造函数Complex operator + (const Complex ,14,8.2.2 运算符重载为成员函数,Complex Complex:operator + (const Complex ,Complex Complex:operator (const Complex ,15,创建对象c,调用其构造函数;调用复制构造函数c在其作用域结束时调用析构函数并被销毁,返回临时对象:直接将对象创建在外部返回值的内存单元,不再创建临时对象。,8.2.2 运算符重载为成员函数,void Complex:display() cout(real,imag)endl; int main() Complex c1(5,4),c2(2,10),c3; coutc1=; c1.display();coutc2=; c2.display();c3=c1-c2;/使用重载运算符完成复数减法coutc3=c1-c2=;c3.display();c3=c1+c2;/使用重载运算符完成复数加法coutc3=c1+c2=;c3.display();return 0;,程序输出的结果为:c1=(5,4)c2=(2,10)c3=c1-c2=(3,-6)c3=c1+c2=(7,14),16,8.2.2 运算符重载为成员函数,运算符成员函数的设计,前置单目运算符 U如果要重载 U 为类成员函数,使之能够实现表达式 : U oprd (例如:+m) 其中 oprd 为A类对象,则 U 应被重载为 A 类的成员函数,无形参。经重载后:表达式 U oprd 相当于 oprd.operator U(),17,8.2.2 运算符重载为成员函数,运算符成员函数的设计,后置单目运算符 +和-如果要重载 +或-为类成员函数,使之能够实现表达式 :oprd+ 或 oprd 其中 oprd 为A类对象,则 +或- 应被重载为 A 类的成员函数,且具有一个 int 类型形参。经重载后,表达式 oprd+ 相当于 oprd.operator +(0),18,8.2.2 运算符重载为成员函数,例8.2,运算符前置+和后置+重载为时钟类的成员函数。前置单目运算符,重载函数没有形参;对于后置单目运算符,重载函数需要有一个整型形参。操作数是时钟类的对象。实现时间增加1秒钟。,19,8_2,8.2.2 运算符重载为成员函数,#includeusing namespace std;class Clock /时钟类声明public:Clock(int h = 0, int m = 0, int s = 0);void showTime() const;Clock ,20,8.2.2 运算符重载为成员函数,Clock ,21,8.2.2 运算符重载为成员函数,Clock Clock:operator +(int) /后置单目运算符重载Clock old = *this;+(*this);return old;,int main()Clock myClock(23,59,59);coutFirst time output:;myClock.showTime();coutmyClock+: ;(myClock+).showTime();cout+myClock: ;(+myClock).showTime();return 0; ,程序运行结果为:First time output: 23:59:59myClock+: 23:59:59+myClock: 0:0:1,22,8.2.2 运算符重载为成员函数,运算符重载为非成员函数,如果需要重载一个运算符,使之能够用于操作某类对象的私有成员,可以此将运算符重载为该类的友元函数。函数的形参代表依自左至右次序排列的各操作数。后置单目运算符 +和-的重载函数,形参列表中要增加一个int,但不必写形参名。,23,8.2.3 运算符重载为非成员函数,运算符重载为非成员函数,双目运算符 B重载后,表达式:oprd1 B oprd2 等同于operator B(oprd1,oprd2 )前置单目运算符 B重载后,表达式 :B oprd 等同于operator B(oprd )后置单目运算符 +和-重载后,表达式 : oprd B 等同于operator B(oprd, 0),24,8.2.3 运算符重载为非成员函数,例8-3,将+、-(双目)重载为复数类的友元函数。两个操作数都是复数类的对象。,25,8_3,8.2.3 运算符重载为非成员函数,#includeusing namespace std; class Complex /复数类声明public:Complex(double r=0.0, double i=0.0):real(r), imag(i)friend Complex operator + (const Complex ,26,8.2.3 运算符重载为非成员函数,Complex operator + (const Complex ,27,8.2.3 运算符重载为非成员函数,28,int main() Complex c1(5,4),c2(2,10),c3; coutc1= c1 endl;coutc2= c2 endl;c3=c1-c2;/使用重载运算符完成复数减法coutc3=c1-c2= c3 endl;c3=c1+c2;/使用重载运算符完成复数加法coutc3=c1+c2= c3 endl;return 0;,程序输出的结果为:c1= (5, 4)c2= (2, 10)c3=c1-c2= (3, -6)c3=c1+c2= (7, 14),8.2.3 运算符重载为非成员函数,本章主要内容,多态性运算符重载虚函数纯虚函数和抽象类,29,8.3 虚函数,#includeusing namespace std; class Pointpublic:Point(double i, double j) x=i; y=j;double getArea() const return 0.0;private:double x, y;class Rectangle: public Pointpublic:Rectangle(double i, double j, double k, double l);double getArea() const return w*h;private:double w, h;,静态绑定,30,8_4,8.3 虚函数,Rectangle:Rectangle(double i, double j , double k, double l) :Point(i,j), w(k), h(l)void fun(Point ,运行结果:Area=0Area=0,31,8.3 虚函数,动态绑定,#includeusing namespace std; class Pointpublic:Point(double i, double j) x=i; y=j;virtual double getArea() const return 0.0;private:double x, y;class Rectangle: public Point public:Rectangle(double i, double j, double k, double l);virtual double getArea() const return w*h;private:double w, h;,32,8_4_1,8.3 虚函数,Rectangle:Rectangle(double i, double j , double k, double l) :Point(i,j),w(k),h(l)void fun(Point ,运行结果:Area=375Area=375,33,8.3 虚函数,虚函数,虚函数是动态绑定的基础。是非静态的成员函数。在类的声明中,在函数原型前加virtualvirtual 只用来说明类声明中的原型,不能用在函数实现时。具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数。本质:是覆盖。调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数。,34,8.3.1 一般虚函数成员,例 8.4,#includeusing namespace std; class Base1 /基类Base1声明public:virtual void display() const; /虚成员函数;void Base1:display() constcoutBase1:display()endl;,35,8_4_2,8.3.1 一般虚函数成员,class Base2: public Base1/公有派生public: void display() const; /覆盖基类虚函数 ;void Base2:display() const coutBase2:display()endl; class Derived: public Base2 /公有派生public: void display() const;void Derived:display() const coutDerived :display()display(); int main() /主函数Base1 b1, *p; /声明基类对象和指针Base2 b2; /声明派生类对象Derived d1; /声明派生类对象p = ,程序的运行结果为:Base1:display()Base2:display()Derived :display(),37,8.3.1 一般虚函数成员,关于虚函数的说明,38,一个函数一旦被说明为虚函数,则无论说明它的类被继承了多少层,在每一层派生类中该函数都保持virtual特性。因此,在派生类中重新定义该函数时,可以不再需要关键字virtual。但习惯上,为了提高程序的可读性,常常在每层派生类中,都重复地使用virtual关键字。,8.3.1 一般虚函数成员,关于虚函数的说明(续),39,当在基类中把成员函数定义为虚函数后,在 其派生类中定义的虚函数,必须与基类中的虚 函数同名,参数的类型、顺序、个数必须一一对应。实现这种动态的多态性,必须使用基类类型 的指针变量或引用,使该指针指向不同的派生类的对象,并通过调用指针所指的虚函数才能实现动态的多态性。,8.3.1 一般虚函数成员,虚函数的限制,(1)只有类的成员函数才能说明为虚函数,因为虚函数仅适用于继承关系的类对象,所以普通函数不能说明为虚函数。(2)一般内联函数不应是虚函数,因为内联函数是在编译时决定其位置。(3)构造函数不能是虚函数。(4)析构函数可以是虚函数。实现运行时多态的同时,保证使用基类类型的指针,就可以调用适当的析构函数,以便针对不同的对象进行清理工作。,40,8.3.1 一般虚函数成员 8.3.2 虚析构函数,41,class Base public:Base();Base:Base() cout Base destructorn;class Derived: public Base public:Derived();Derived();private:int *i_pointer;,p319-321,例8-5,8.3.2 虚析构函数,42,Derived:Derived()i_pointer = new int(0); Derived:Derived() cout构造型来表示。,44,8.4.1 纯虚函数,抽象类,带有纯虚函数的类,称为抽象类。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论