董正言 面向对象++程序设计第九章
合集下载
面向对象程序设计第九章
9.2.1 预定义的插入符(续)
输出 The string is: I love C++ I love C++ I love this is a string this i
9.2.2 预定义的提取符
1、预定义提取符的格式 istream& istream::operator >>(type& obj); 其中:type为char、int、short、long类型和它 们的unsigned和signed类型,以及float、double、 long double、char *; 2、说明 一般情况下将提取符作用于cin对象; 输入语句中可以串联多个提取运算符,每个提 取符后为一表达式,该表达式是获得输入值的 变量或对象;
9.3 插入符和提取符的重载(续)
例9.7:分析下列程序的输出结果。 #include <iostream.h> class Date { public: Date(int y,int m,int d) { Year=y; Month=m; Day=d; } friend ostream& operator << (ostream& stream,Date& date); friend istream& operator >> (istream& stream,Date& date);
9.2.2 预定义的提取符(续)
例9.6:分析下列程序的输出结果。 #include <iostream.h> void main() { 输入: const int S=80; Input... char buf[S]=""; abcd<Enter> cout<<"Input…"<<endl; efgh<Enter> cin>>read(buf,s); ijkl<Enter> cout<<endl; cout<<buf<<endl; } 输 出 Input… abcd efgh ijkl
清华面向对象程序设计:第09章
bel组件 . 组件 Label被称为标签组件,它是一种用来显示说明 性的静态文本的组件.用户不能直接地编辑它, 但可以在应用程序中,通过调用Label提供的成 员方法更换文本的内容. Label类提供了三种构造方法的格式: Label() Label(String text) Label(String text, int alignment) alignment可以是Label类定义的整型常量,比如: LEFT(居左),CENTER(居中)和RIGHT (居右).
java.awt是java1.1用来建立GUI的图形包, 这 里 的 " awt" 是 抽 象 窗 口 工 具 包 (Abstract Windowing Toolkit)的缩写, 其 中 的 组 件 常 被 称 为 AWT 组 件 . javax.swing是Java2提出的AWT的改进包, 它主要改善了组件的显示外观,增强了 组件的控制能力.
4.Checkbox组件 . 组件 Checkbox被称为复选组件,它是一种图形化的, 可以设置"on"和"off"两种状态的组件.用鼠 标 点 击 一 个 复 选 按 钮 , 可 以 使 其 在 " on" 和 "off"之间进行切换.不仅如此,还可以将几 个复选按钮利用CheckboxGroup组件绑定成一 组,使得每一组复选按钮在每一时刻只有一个 处于"on"状态. 在Checkbox类中,提供了四种构造方法的格式: Checkbox() Checkbox(String label) Checkbox(String label, boolean state) Checkbox(String label, boolean state, CheckboxGroup group)
董正言 面向对象++程序设计第九章
9.1 什么是多态
•
•
•
•
•
在面向对象程序设计技术中,简单地说,多态是指给不同类型的对象发送相 同的消息时,这些不同类型的对象会做出不同的反应,产生不同的行为,导 致不同的结果。 具体而言,多态性是指:在由继承形成的类家族的各个类中可以存在具有相 同名称的方法,这些同名的方法在不同类中的具体行为各不相同;当使用基 类的引用变量或指针引用不同的派生类对象时,如果给它们发送相同的消息, 请求它们执行同名的方法,则根据对象实际所属的类,在程序运行时动态地 选用在该类中定义的方法,不同类的对象响应消息的具体行为各不相同。 例如对于描述几何图形的类家族,每个图形类中都有计算面积的方法;当利 用向上转型技术,使用基类Shape的指针引用派生类对象,并通过该指针调 用计算面积的方法时,根据该对象所属的类型,在程序运行过程中动态地来 选用相应类中的方法来计算具体图形的面积;若该对象是一个圆类的对象, 则应该选取圆类中计算面积的方法;若该对象是一个矩形,则应该选用矩形 类中计算面积的方法;这就是所谓的“运行时多态” 。 利用多态技术,可以使用通用的语句形式来处理不同类的对象。多态机制不 仅可以增加程序设计的灵活性,而且使编程者不必过多地考虑具体类型实现 方法的细节,从而设计出通用于于各种不同类型的“一般化”程序。这种一 般化的程序具有更好的可读性、可重用性和可扩充性。 在C++语言中,多态性是通过类的虚成员函数实现的;动态绑定技术为使用 虚函数提供了保证;而对象的向上转型则是实现多态的必要条件。
• C++中现有的绝大多数运算符只能以基本数据类型的量作 为其操作的对象。运算符重载就是要给现有的运算符赋予 新的功能,使其可以操作类的对象。 • 运算符重载的本质是函数重载。如果为某个类设计了运算 符op的重载函数,则当使用op操作该类的对象时,编译 器将调用运算符重载函数完成操作任务。 • 由于运算符重载函数的调用方式是静态绑定,所以可以将 运算符重载称之为编译期多态。
面向对象程序设计C++第9章-课件
函数原型
int get(void); istream& get(char& c); istream& get(char *s,int n,char ch=‟\n‟);
例如: char c1,c2,a[80]; c1=cin.get(); cin.get(c2); cin.get(a,21,‟#‟);
c++程序设计简明教程
格式状态标志
ios::adjustfield标志组 ios::left ios::right 输出时左对齐 输出时右对齐
ios::internal 符号和基数标志左对齐, 数值右对齐,中间用字 符填充
c++程序设计简明教程
ios::basefield标志组
ios::dec 以十进制为基数输出
c++程序设计简明教程
例9.5 操作符应用之一。
#include<iostream.h> #include<iomanip.h> int main() { int i; for(i=1;i<=4;i++) { cout<<setw(4-i)<<setfill(' '); if(cout.width()!=0) cout<<" "; cout<<setw(2*i1)<<setfill('*')<<"*"<<endl; } return(0); }
c++程序设计简明教程
9.3.3 getline
函数原型 istream& getline(char *s,int n,char ch=‟\n‟); 例如: char a[80]; cin.getline(a,21,‟#‟)
int get(void); istream& get(char& c); istream& get(char *s,int n,char ch=‟\n‟);
例如: char c1,c2,a[80]; c1=cin.get(); cin.get(c2); cin.get(a,21,‟#‟);
c++程序设计简明教程
格式状态标志
ios::adjustfield标志组 ios::left ios::right 输出时左对齐 输出时右对齐
ios::internal 符号和基数标志左对齐, 数值右对齐,中间用字 符填充
c++程序设计简明教程
ios::basefield标志组
ios::dec 以十进制为基数输出
c++程序设计简明教程
例9.5 操作符应用之一。
#include<iostream.h> #include<iomanip.h> int main() { int i; for(i=1;i<=4;i++) { cout<<setw(4-i)<<setfill(' '); if(cout.width()!=0) cout<<" "; cout<<setw(2*i1)<<setfill('*')<<"*"<<endl; } return(0); }
c++程序设计简明教程
9.3.3 getline
函数原型 istream& getline(char *s,int n,char ch=‟\n‟); 例如: char a[80]; cin.getline(a,21,‟#‟)
第9章 面向对象的程序设计
正式定名为春节,是辛亥革命后的事。由于那时要改用阳历,为了区分农、阳两节,所以只好
将 农 历 正 月 初 一 改 名 为 “ 春 节”。 ");
MC="春 节 ";
LN=S1.length
//将字符串 S1 的长度赋给变量 LN
}
}
AN2.onPress=function(){
k++;
if (Math.ceil(k/2)<>k/2){
图 911 “滚动文字”影片播放后的一幅画面
图 912 “滚动文字”影片播放后的一幅画面
(1)新 建 一 个 Flash 文 档 ,设 置 舞 台 工 作 区 宽 为 800 像 素 ,高 为 160 像 素 ,背 景 色 为 白 色 。
选中“图层 1”图层的第 1 帧,导入 4 幅有关我国名胜图像,调整它们的大小均为高 130 像素,
【相关知识】面向对象编程和字符串对象
1.面向对象编程的基本概念
在20世纪80年代提出了面向对象的程序设计(Object Oriented Programming,简称OOP), 它能够有效地改进结构化程序设计中存在的问题,它采用面向对象的方法来解决问题,不再将 问题分解为过程,而是将问题分解为对象。在结构化的程序设计中,我们要解决某一个问题, 是将问题进行分解,然后用许多功能不同的函数来实现,数据与函数是分离的。面向对象的程 序 设 计 方 法 的 思 考 方 式 是 面 向 问 题 结构 的 ,它 认 为 现 实 世 界 是 由 对 象 组 成 的,要 解 决 某 个 问 题 , 必须要首先确定这个问题是由哪些对象组成的。
长度。例如:在舞台工作区内创建一个动态文本框,它的变量名字为LN,在“图层1”图层第1
09第九章 面向对象的程序设计.doc
《VFP基础教程》
清华大学出版社
2. 类(Class) ) 类是一组具有公共属性和公共方法对象的抽象表示。 引入类的主要目的是简化对象的定义。 类的基本特性是封装性、继承性和多态性。 类的封装性 是指将对象的数据和操作都包含在对象中,如果要对 对象进行操作,只需向对象发送消息,不必知道对象内 部是如何处理该消息的。 类的继承性 是指可以在一个现有的类(称为父类)的基础上增加一 些新的属性与行为,从而生成一个新的类(称为子类),
清华大学出版社
第九章 Visual FoxPro面向对象的 程序设计
本章教学要求:掌握面向对象程序设计的基本概念, 熟习VFP中常用的类,掌握类的设计基本方法。 9.1 面向对象程序设计的基本概念 9.2 Visual FoxPro中的对象和类 9.3 Visual FoxPro类的设计 9.4 对类对象的引用
《VFP基础教程》
清华大学出版社
控件 线条(Line) 容器 命令按钮组 (Command Button Group)
列表框(List Box) OLE绑定型控件(OLE Bound Control) OLE容器控件(OLE Container Control) 形状(Shape) 微调(Spinner) 文本框(Text Box)
《VFP基础教程》
清华大学出版社
图9-1 “新建”对话框
《VFP基础教程》
清华大学出版社
在图9-2中单击“新建文件”按钮按钮,屏幕上出现“新 建类”对话框,如图9-2所示。
图9-2 “新建”类对话框
《VFP基础教程》
清华大学出版社
在图9-2中有3个输入框: 类名:输入要新建类的类名,例如MyDateTime 。 派生于:指定要新立的类从哪一个类中派生出,即新 建类的基类,在本例中,由于显示日期时间需要一个标 签控件和一个计时器,所示从基类Container(容器)类 中派生新类。 存储于:新建成类的类库文件存储在哪个文件中,保 存Visual FoxPro中类库文件的文件扩展名是.VCX。 在图9-2中输入完相关内容后,单击“确定”按钮,屏 幕上出现“类设计器”窗口,如图9-3所示 。
面向对象程序设计第9章
第 9 章
图形用户界面程序设计
本章主要内容
Java图形用户界面(GUI) Java图形用户界面(GUI) 图形用户界面 用Swing创建图形用户界面 Swing创建图形用户界面 事件处理机制
9.1 Java图形用户界面概述 Java图形用户界面概述
顾名思义,图形用户界面( 顾名思义,图形用户界面(Graphics Interface,缩写GUI GUI) User Interface,缩写GUI)是指以图形 的显示方式与用户实现交互操作的应用 程序界面。Java提供了十分完善的图形 程序界面。Java提供了十分完善的图形 用户界面功能, 用户界面功能,使得软件开发人员可以 轻而易举地开发出功能强大、界面友善、 轻而易举地开发出功能强大、界面友善、 安全可靠的应用软件。 安全可靠的应用软件。
设计用户界面需要经历4个基本步骤: 设计用户界面需要经历4个基本步骤: (1)创建和设置组件 (2)将组件加入到容器中 (3)布局组件 (4)处理由组件产生的事件
对于用户界面,设计界面只是第一步。 对于用户界面,设计界面只是第一步。除 了设计和控制可视化组件的显示外观外, 了设计和控制可视化组件的显示外观外, 还需要具有处理用户操作请求的能力,即 还需要具有处理用户操作请求的能力, 事件处理。 事件处理。 事件处理的类在java.event包中。 事件处理的类在java.event包中。 java.event包中
JFrame类的部分成员方法 JFrame类的部分成员方法
int getDefaultCloseOperation() void setDefaultCloseOperation() void pack() Dimension getSize() void setSize(int width,int height) void setSize(Dimension size) Rectangle getBounds() void setBounds(int xleft,int yleft,int width,int height) void setBounds(Rectangle size) Container getContentPane() JMenuBar getJMnuBar()
图形用户界面程序设计
本章主要内容
Java图形用户界面(GUI) Java图形用户界面(GUI) 图形用户界面 用Swing创建图形用户界面 Swing创建图形用户界面 事件处理机制
9.1 Java图形用户界面概述 Java图形用户界面概述
顾名思义,图形用户界面( 顾名思义,图形用户界面(Graphics Interface,缩写GUI GUI) User Interface,缩写GUI)是指以图形 的显示方式与用户实现交互操作的应用 程序界面。Java提供了十分完善的图形 程序界面。Java提供了十分完善的图形 用户界面功能, 用户界面功能,使得软件开发人员可以 轻而易举地开发出功能强大、界面友善、 轻而易举地开发出功能强大、界面友善、 安全可靠的应用软件。 安全可靠的应用软件。
设计用户界面需要经历4个基本步骤: 设计用户界面需要经历4个基本步骤: (1)创建和设置组件 (2)将组件加入到容器中 (3)布局组件 (4)处理由组件产生的事件
对于用户界面,设计界面只是第一步。 对于用户界面,设计界面只是第一步。除 了设计和控制可视化组件的显示外观外, 了设计和控制可视化组件的显示外观外, 还需要具有处理用户操作请求的能力,即 还需要具有处理用户操作请求的能力, 事件处理。 事件处理。 事件处理的类在java.event包中。 事件处理的类在java.event包中。 java.event包中
JFrame类的部分成员方法 JFrame类的部分成员方法
int getDefaultCloseOperation() void setDefaultCloseOperation() void pack() Dimension getSize() void setSize(int width,int height) void setSize(Dimension size) Rectangle getBounds() void setBounds(int xleft,int yleft,int width,int height) void setBounds(Rectangle size) Container getContentPane() JMenuBar getJMnuBar()
管理信息系统-第9章-面向对象的系统开发-Fengppt课件
1
• 同一对象可以接收不同形式的多个消息,产生不同响应;
2
• 一条消息可以发送给不同的对象,消息的解释完全由接
收对象完成;
3
• 对于传来的消息,对象可以返回相应的回答信息,也可 以不返回,即消息响应不是必须的。
2024/8/2
第九章 面向对象的系统开发
5
1.1.4继承
继承是指一个类(即称子类)因承袭而具有另一个类(或称父类)的能力和特征的 机制或关系。继承是一种联结类的层次模型,允许并鼓励类的重用。继承是类之间 的重要关系。依赖继承机制,可由类产生对象,或由已知类定义其他类。
1、识别接口对象和控制对象
1、接口对象从系统外部获取信息,并为之提供信息; 2、能否承担某项功能是控制对象存在的依据。
2、确定实体对象、接口对象和控制对象之间的各种关系
1)静态联系。实体对象间的静态联系在分析阶段已经确定。
2)消息连接。接口对象与实体对象、控制对象与实体对象、接口对象与控制对象 间都只存在消息连接。
继承 数据结构
• 描述子类承袭父类的名称,以及结构与 功能。
• 对该类数据包含数据项的描述
操作
• 该类通用功能的具体实现方法
接口
• 面向其它类的统一的外部通讯协议。
2024/8/2
第九章 面向对象的系统开发
4ቤተ መጻሕፍቲ ባይዱ
1.1.3消息
消息是实现对象与对象间相互合作的通信载体,是连接对象的纽带。从实现的角度 看,消息就是请求对象执行某个处理或提供某些信息的要求,既可以是数据流,又 可以是控制流。
本章内容
• 第一节 面向对象方法的基础理论 • 第二节 面向对象方法的建模工具 • 第三节 面向对象的分析与设计过程 • 第四节 面向对象的系统实施
数据库软件Visual Foxpro课件第九章 面向对象的程序设计
象。如:表单、表格 2) 控件类:不能包含其他对象。如:标签、按钮、文本框
2. 子类:是指以某个类为起点创建的新类。如:从基类派生新 类时,基类为父类,派生的新类为子类
2021/8/5
9
VFP基类
控件类
复选框(Check Box) 组合框(Combo Box) 命令按钮(Command Button) 控制(Control) 自定义(Custom) 编辑框(Edit Box) 列头(Header) 图像(Image) 标签(Label) 线(Line) 列表框(List Box) ActiveX绑定(OLE Bound Control) ActiveX控件(OLE Control) 形状(Shape) 微调按钮(Spinner) 文本框(Text Box) 20定21时/8/5器(Timer)
输入过程
2021/8/5
查询过程
修改过程 删除过程
1
※ 面向过程的程序设计的缺点 1) 软件开发周期长 2) 不便维护,不易修改 3) 软件难以再次利用
表单
2. 面向对象程序设计(OOP:Object-Oriented Programming)
面向对象程序设计是按照人们认识世界的方法和思维方式来 分析问题、解决问题,其中对象作为最基本的元素是核心。
第九章 面向对象的程序设计
9.1 面向对象程序设计的概念
一 面向对象的程序设计 1. 面向过程(结构化)的程序设计 面向过程的程序设计的设计方法,是采用自顶向下,逐 步求精的方法将程序按功能划分成若干个相互独立的程序模 块,然后将这些程序模块组装起来构成一个完整的程序。
例9-1 一个物资管理系统的模块结构图 主控程序
2021/8/5
8
III. 多态性(polymorphism) :是指一些关联的类包含同名 的方法程序,方法程序的内容可以不同
2. 子类:是指以某个类为起点创建的新类。如:从基类派生新 类时,基类为父类,派生的新类为子类
2021/8/5
9
VFP基类
控件类
复选框(Check Box) 组合框(Combo Box) 命令按钮(Command Button) 控制(Control) 自定义(Custom) 编辑框(Edit Box) 列头(Header) 图像(Image) 标签(Label) 线(Line) 列表框(List Box) ActiveX绑定(OLE Bound Control) ActiveX控件(OLE Control) 形状(Shape) 微调按钮(Spinner) 文本框(Text Box) 20定21时/8/5器(Timer)
输入过程
2021/8/5
查询过程
修改过程 删除过程
1
※ 面向过程的程序设计的缺点 1) 软件开发周期长 2) 不便维护,不易修改 3) 软件难以再次利用
表单
2. 面向对象程序设计(OOP:Object-Oriented Programming)
面向对象程序设计是按照人们认识世界的方法和思维方式来 分析问题、解决问题,其中对象作为最基本的元素是核心。
第九章 面向对象的程序设计
9.1 面向对象程序设计的概念
一 面向对象的程序设计 1. 面向过程(结构化)的程序设计 面向过程的程序设计的设计方法,是采用自顶向下,逐 步求精的方法将程序按功能划分成若干个相互独立的程序模 块,然后将这些程序模块组装起来构成一个完整的程序。
例9-1 一个物资管理系统的模块结构图 主控程序
2021/8/5
8
III. 多态性(polymorphism) :是指一些关联的类包含同名 的方法程序,方法程序的内容可以不同
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9.2 虚函数和动态绑定
使用虚函数实现多态调用(1)
• 第8章的例8.11试图创建一个通用的函数displayShapeArea,用来输 出各种图形的面积 ,代码如下:
void displayShapeArea(Shape *s) //函数的参数为基类的指针 { cout<<"图形的面积为:"<<s->area()<<endl;//通过基类指针只能调用基类中定义的成员函 } void main() { Shape *s1,*s2,*s3; //定义基类的指针 Circle c(10.0); Rectangle r(15.0,10.0); Cylinder cy(10.0,20.0); s1=&c; //基类指针指向派生类对象 s2=&r; //基类指针指向派生类对象 s3=&cy; //基类指针指向派生类对象 displayShapeArea(s1); displayShapeArea(s2); displayShapeArea(s3); }
用类的成员函数实现运算符重载
• 当运算符重载函数被定义为类的成员函数时,声明和定义的语法格式如下: 在类中声明运算符重载函数(类的成员函数) : 返回值类型 operator 运算符 (形参列表); 定义运算符重载函数(类的成员函数) : 返回值类型 类名::operator 运算符 (形参列表) { 函数体; }
使用虚函数实现多态调用(2)
• 程序中用3个Shape类的指针s1、s2、s3分别引用Circle类、Rectangle 类和Cylinder类的对象c、r和cy,并用s1、s2、s3作参数分别调用函数 displayShapeArea。但程序的运行结果并没有如期望的一样输出3个不 同对象的面积。这是因为虽然可以用基类指针引用派生类对象,但是 通过这些指针只能调用在基类中定义的成员函数。那么当基类指针指 向派生类对象时,能否通过基类的指针调用派生类中定义的成员函数 呢?解决问题的方法是将成员函数声明为虚函数。 • 声明虚成员函数的语法格式如下: virtual 返回值类型 成员函数名(型参列表); • 如果在基类中声明虚成员函数,则在所有派生类中该函数都是虚函数, 即使在派生类中声明该函数时没有使用关键字virtual。 • 当使用基类指针或引用调用虚成员函数时,实际调用的是指针指向的 具体对象所属类中定义(覆盖)的成员函数。这种函数调用方式称为多态 调用。
• C++中现有的绝大多数运算符只能以基本数据类型的量作 为其操作的对象。运算符重载就是要给现有的运算符赋予 新的功能,使其可以操作类的对象。 • 运算符重载的本质是函数重载。如果为某个类设计了运算 符op的重载函数,则当使用op操作该类的对象时,编译 器将调用运算符重载函数完成操作任务。 • 由于运算符重载函数的调用方式是静态绑定,所以可以将 运算符重载称之为编译期多态。
第九章 多态
本章要点
• • • • • 什么是多态 虚函数和动态绑定 纯虚函数和抽象类 编译期多态―运算符重载 运行时类型识别(RTTI)
9.1 什么是多态
•
•
•
•
•
在面向对象程序设计技术中,简单地说,多态是指给不同类型的对象发送相 同的消息时,这些不同类型的对象会做出不同的反应,产生不同的行为,导 致不同的结果。 具体而言,多态性是指:在由继承形成的类家族的各个类中可以存在具有相 同名称的方法,这些同名的方法在不同类中的具体行为各不相同;当使用基 类的引用变量或指针引用不同的派生类对象时,如果给它们发送相同的消息, 请求它们执行同名的方法,则根据对象实际所属的类,在程序运行时动态地 选用在该类中定义的方法,不同类的对象响应消息的具体行为各不相同。 例如对于描述几何图形的类家族,每个图形类中都有计算面积的方法;当利 用向上转型技术,使用基类Shape的指针引用派生类对象,并通过该指针调 用计算面积的方法时,根据该对象所属的类型,在程序运行过程中动态地来 选用相应类中的方法来计算具体图形的面积;若该对象是一个圆类的对象, 则应该选取圆类中计算面积的方法;若该对象是一个矩形,则应该选用矩形 类中计算面积的方法;这就是所谓的“运行时多态” 。 利用多态技术,可以使用通用的语句形式来处理不同类的对象。多态机制不 仅可以增加程序设计的灵活性,而且使编程者不必过多地考虑具体类型实现 方法的细节,从而设计出通用于于各种不同类型的“一般化”程序。这种一 般化的程序具有更好的可读性、可重用性和可扩充性。 在C++语言中,多态性是通过类的虚成员函数实现的;动态绑定技术为使用 虚函数提供了保证;而对象的向上转型则是实现多态的必要条件。
形参列表中是运算符的操作对象,需要注意,因为被定义为是类的成员函数,所以参 数的个数应该比运算符实际的操作数个数少一个,因为调用函数的对象本身就是运算 符的一个操作数。例如,如果为A类重载了加法运算符“+”,用来完成两个A类对象的 相加操作,且运算符重载函数为类的成员函数,则函数的声明语句为: A operator+ (A a); 执行下面的语句时将调用这个运算符重载函数: a3=a1+a2; 其中,a1、a2、a3都是A类的对象,而这条语句等价于下面的语句: a3=a1.operator+(a2);
例9.1 修改l例8.11中的程序,将Shape类的成员函数area声 明为虚函数。并对其进行多态调用。
使用虚函数实现多态调用(3)
• 注意:虚函数的声明应该放在基类中,如果只在派生类中 将成员函数声明为虚函数,则即使基类指针实际指向的是 派生类的对象,也不能通过该指针调用派生类中的虚成员 函数。例如,如果在上例中没有将Shape类中的area函数 声明为虚函数,而将其派生类Circle和Rectangle中的area 声明为虚函数,则再次运行程序后,仍然不能得到预期的 结果 。 • 如果想在某个类层次中实现多态,则应该在这个层次中的 基类里声明虚函数。
例9.3 随机地创建图形派生类对象,并使用基类指针对该对 象的虚成员函数进行多态调用。
题目要求: (1)本例中将定义一个函数creatOneShape,该函数根据一个随机产生的整数 值,在程序运行过程中动态地创建派生类的对象,并返回一个指向该对象的 Shape类指针。 (2)随机整数通过调用C++库函数rand产生,随机整数的范围是0到2,当产生 的随机整数为0时,函数creatOneShape将动态创建一个Circle类的对象;当产 生的随机整数为1时,函数creatOneShape将动态创建一个Rectangle类的对象; 当产生的随机整数为2时,函数creatOneShape将动态创建一个Cylinder类的对 象。 (3)在main函数中将使用函数creatOneShape返回的对象指针作为参数调用函 数displayShapeArea输出图形的相关信息和面积值。 问题分析:由于本例中的对象是在程序运行期动态产生的,所以在程序编译期是 无法确定对象类型的。也就是说,在程序编译期,编译器无法根据对象类型对虚 函数displayInfo的调用进行静态绑定;而通过程序的运行结果,可以看到,实 际上程序对虚函数displayInfo进行的是多态调用。所以对虚函数的调用必须使 用动态绑定技术。
例9.2 在某个类的层次中利用虚函数实现多态 。
பைடு நூலகம்
虚函数和动态绑定
• 为什么只有虚成员函数才能实现多态调用呢?这是由编译器处理函数 调用的方式决定的。非虚函数的调用方式为静态绑定,而虚函数的调 用方式为动态绑定。 • 绑定是指将函数调用和实际的函数相连接的过程。分为静态绑定和动 态绑定。 • 静态绑定是在程序编译时,就确定要调用的函数,并用函数的相对地 址直接调用函数,所以静态绑定又被称为编译期绑定或前期绑定。 C++中所有的非虚函数都使用静态绑定方式进行调用,对于类的非虚 成员函数而言,当该函数被调用时,编译器将根据调用该函数的对象、 指针或引用的类型决定应该调用哪个类中的成员函数。 • 动态绑定是指,在程序编译期无法确定要调用的函数,在程序的运行 过程中,根据调用函数的指针或引用变量所引用的对象的具体类型动 态地确定要调用的函数。所以动态绑定又被称为运行期绑定或后期绑 定。C++中的虚成员函数使用动态绑定方式进行调用。 • 下例修改例9.1中的程序,进一步阐明如何使用动态绑定和虚函数来 实现运行时多态。
例9.5 为Time类重载二元运算符“+”、一元前置自加运算 符“++”、一元后置自加运算符“++”。其中二元运算符“+” 用来将两个时间相加得到一个新的时间值;一元自加运算符 “++”用来将当前时间加1秒钟 。
声明虚函数时,应注意以下几点
• 不能将类的静态成员函数声明为虚函数 ; • 不能将类的构造函数声明为虚函数; • 应该把类的析构函数声明为虚函。
9.3 纯虚函数和抽象类
• 例9.3的Shape类中声明了虚函数area和displayInfo,分别用来计算图形的 面积和显示具体图形的相关信息。在Shape类中实现这两个函数几乎是毫无 意义的,因为Shape本身是一个抽象的概念,并不代表任何具体的图形,所 以也无从计算它的面积和输出与具体图形相关的信息。通常可以将这样的函 数声明为纯虚函数。声明纯虚函数的语法格式如下: virtual 返回值类型 函数名(形参列表) = 0; C++允许不为纯虚函数提供具体的实现。而包含了纯虚函数的类称为抽象 类。C++规定不能创建抽象类的实例(对象)。 抽象类的派生类应该为其继承的纯虚函数提供具体的实现,否则它们也包 含了纯虚函数,变成了抽象类。 虽然不能声明抽象基类的实例,但是仍然可以声明抽象基类的指针,并利用 向上转型技术令其引用派生类的对象。例如下面的语句是合法的。 Shape ptr; Circle c; ptr=&c;
C++对于运算符重载的几点限定