刘胥影 liuxy@seu.edu.cn 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 liuxy@seu.edu.cn 东南大学计算机学院.

Slides:



Advertisements
Similar presentations
口試準備及口語表達技巧 民國 98 年 2 月 26 日 12:00pm 國立三重高中 陸芳瑜老師 1.
Advertisements

第一章 面向对象程序设计.
第九讲 类与对象 (I)面向对象基础.
第6章 多态性与虚函数.
程設一.
類別與物件 Class & Object.
類別的繼承-一般關係: 繼承是宣告的類別繼承現存類別的部份或全部的成員資料和方法 , 新增額外的成員資料和方法或覆寫和隱藏繼承類別的方法
Ch07 介面與多重繼承 物件導向程式設計(II).
第八章 类和对象.
JAVA程序设计 (03) JAVA Programming
再回首: Java关键字 数据类型:byte boolean char double float int long short ,
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
第四章 在 C# 中实现 OOP 概念.
4.1 概述 4.2 类与对象的实现 4.3 对象的初始化和析构 4.4 类的包含 4.5 类模板
Derived Class 前言 衍生類別的定義 單一繼承 public, protected, 和 privated 基底類別
程式語言 -Visual Basic 變數、常數與資料型態.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
Scope & Lifetime 前言 Local Scope Global Functions & Objects
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
Java 程式設計 講師:FrankLin.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
刘胥影 东南大学计算机学院 面向对象程序设计1 2011~2012第3学期 刘胥影 东南大学计算机学院.
第六章 继承性和派生类 胡昊 南京大学计算机系软件所.
第一章 程序的基本结构. 第一章 程序的基本结构 教材及授课结构 本章目标 基本内容 扩展阅读 上机指导 应用举例 习题.
刘胥影 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 东南大学计算机学院.
Object-Oriented Programming:
類別樣板 Class Template 類似函式樣板 由類別樣板產生的類別稱為類別樣版的實體(instance)
西安交通大学 计算机教学实验中心 大学C++程序设计教程 西安交通大学 计算机教学实验中心
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
Java软件设计基础 5. 继承与多态.
Object-Oriented Programming in C++ 第一章 C++的初步知识
程序设计期末复习 黎金宁
第三章 C++中的C 面向对象程序设计(C++).
Java程序设计 第9章 继承和多态.
Object-Oriented Programming: Polymorphism
C#面向对象程序设计 $7 继承和多态性.
類別的繼承 Vehicle Car.
第6章 继承和接口设计 6.1 继 承 6.2 多态性 6.3 抽象类 6.4 接口 6.5 接口在集合排序中的应用.
第四章 小技巧.
类类型 C++支持的内置类型和操作,如 int i=10; i=i%6; i=i+4;
Php class 組員: 賴羿陵 林昱廷 莊正暉 張雅晴
C/C++/Java 哪些值不是头等程序对象
第六章 属性、索引器、委托和事件.
第16章 虛擬與多形 16-1 虛擬函數 16-2 純虛擬函數與抽象類別 16-3 多形 16-4 虛擬繼承與虛擬解構子.
第7章 繼承/多型/介面 注意: 本投影片僅供本書上課教師使用,非經同意請勿上網轉載或供拷貝.
C++大学基础教程 第11章 多态性 北京科技大学 信息基础科学系 2019/4/8 北京科技大学.
第二章 基本数据类型及运算 C数据类型概述 基本数据类型 运算符和表达式 混合运算与类型转换 数据的输入输出 顺序程序设计举例.
Speaker: Liu Yu-Jiun Date: 2009/4/29
C#程序设计基础 $3 成员、变量和常量.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
C++语言程序设计 C++语言程序设计 第九章 类的特殊成员 第十一组 C++语言程序设计.
第10讲 构造函数和析构函数 构造函数 析构函数 This 指针.
Inheritance -II.
Object-Oriented Programming in C++ 第二章 类和对象
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
第九章 物件導向-進階.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第 3 章 类的基础部分 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
#include <iostream.h>
方法進階及物件導向基礎 Lecturer: 楊昌樺.
C++语言程序设计 C++语言程序设计 第八章 继承 C++语言程序设计.
第 5 章 继承、多态和虚函数 陈哲 副教授 南京航空航天大学 计算机科学与技术学院.
第一讲 面向对象方法学与信息系统建模.
谭浩强编著 C++面向对象程序设计 授课教师:姬广永 学习网站:
C++语言程序设计 C++语言程序设计 第十章 多态 第十一组 C++语言程序设计.
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
C++语言程序设计 C++语言程序设计 第十一章 异常处理 C++语言程序设计.
C++语言程序设计(第4版) 第七章 继承与派生 数学与统计科学学院 胡凤珠.
資料結構與C++程式設計進階 C++與資料結構 講師:林業峻 CSIE, NTU 7/ 5, 2010.
第6章 继承和多态 伍孝金
Presentation transcript:

刘胥影 liuxy@seu.edu.cn 东南大学计算机学院 面向对象程序设计1 2010~2011第3学期 刘胥影 liuxy@seu.edu.cn 东南大学计算机学院

Polymorphism 教学要求与安排 教学要求 13.7~13.9不要求 东南大学计算机学院 11/11/2018

Polymorphism 13.1 多态性 13.2 多态性实例 13.3 抽象类和纯虚函数 13.4 实例研究:工资发放系统 (chap13.1, 13.2, 13.3) (chap13.3) (chap13.5) (chap13.6)

多态性 什么是多态性?(What) 如何产生多态性?(How) 为何需要多态性?(Why)

对于相同的消息net_price,类继承层次中 不同的对象根据自己的特点自动进行相应的响应 13.1多态性 什么是多态性?(1) 例1. 书 Item_base 打折书 Bulk_item 消息 响应 Item_base net_price 对象类型 Bulk_item net_price = cnt * price net_price= 𝑐𝑛𝑡∗ 1−𝑑𝑖𝑠𝑐𝑜𝑢𝑛𝑡 ∗𝑝𝑟𝑖𝑐𝑒, 𝑖𝑓 𝑐𝑛𝑡≥ min _𝑞𝑡𝑦 𝑐𝑛𝑡∗𝑝𝑟𝑖𝑐𝑒, 𝑒𝑙𝑠𝑒 对于相同的消息net_price,类继承层次中 不同的对象根据自己的特点自动进行相应的响应 东南大学计算机学院 11/11/2018

什么是多态性?(2) 例2. 对于相同的消息earnings,类继承层次中 不同的对象根据自己的特点自动执行相应的响应 佣金雇员 13.1多态性 什么是多态性?(2) 例2. 佣金雇员 CommissionEmployee 带底薪佣金雇员 BasePlusCommissionEmployee 消息 响应 Commission Employee BasePlusCommissionEmployee earnings 对象类型 grossSales×commissionRate baseSalary + grossSales×commissionRate 对于相同的消息earnings,类继承层次中 不同的对象根据自己的特点自动执行相应的响应 东南大学计算机学院 11/11/2018

什么是多态性?(3) 例3. 二维图形 TwoDimensionalShape 矩形 圆 Rectangle Circle 正方形 13.1多态性 什么是多态性?(3) 例3. 二维图形 TwoDimensionalShape 圆 Circle 矩形 Rectangle 正方形 Square 东南大学计算机学院 11/11/2018

对于相同的消息draw/area,类继承层次中 不同的对象根据自己的特点自动执行相应的响应 13.1多态性 什么是多态性?(4) 消息 对象类型 响应 Circle Rectangle Square draw Circle Rectangle Square area 𝑎𝑟𝑒𝑎=𝑎𝑏 𝑎𝑟𝑒𝑎= 𝑎 2 𝑎𝑟𝑒𝑎=𝜋 𝑟 2 对于相同的消息draw/area,类继承层次中 不同的对象根据自己的特点自动执行相应的响应 东南大学计算机学院 11/11/2018

什么是多态性?(5) 多态性 同样的消息在发送给不同的对象时会产生多种形式的结果 多态性指:不同对象对同一消息的响应是多态的 13.1多态性 关键概念 消息 对象类型 响应 Circle Rectangle Square draw 同样的消息在发送给不同的对象时会产生多种形式的结果 多态性指:不同对象对同一消息的响应是多态的 东南大学计算机学院 11/11/2018

如何产生多态性? 多态性产生的条件 通过基类的指针或引用调用virtual函数时 知识结构 13.1多态性 二者缺一不可 多态性的产生 继承中指针和对象的关系 virtual函数与动态绑定 知识结构 条件1:基类的指针或引用 条件2:virtual函数 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(1) 句柄 对象名 对象的指针 对象的引用 13.1多态性 A a; a.f(); //通过对象名调用 A *pr = &a; pr->f(); //通过指针调用 A &ref = a; ref.f() //通过引用调用 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(2)  指针(引用)类型 对象类型 基类指针 基类对象 派生类指针 派生类对象 is-a 基类对象 派生类对象 13.1多态性 继承中指针和对象的关系(2) 指针(引用)类型 对象类型 基类指针 基类对象  派生类指针 派生类对象 基类对象 派生类对象 is-a 东南大学计算机学院 11/11/2018

 继承中指针和对象的关系(3)  指针(引用)类型 对象类型 基类指针 基类对象 派生类指针 派生类对象 is-a 基类对象 派生类对象 13.1多态性 继承中指针和对象的关系(3) 指针(引用)类型 对象类型 基类指针 基类对象  派生类指针 派生类对象 基类对象 派生类对象 is-a  东南大学计算机学院 11/11/2018

 继承中指针和对象的关系(4) is-a关系 is-a is-a 基类对象 -x -y 派生类对象 -z 基类对象 派生类对象 基类对象 13.1多态性 继承中指针和对象的关系(4) is-a关系 基类对象 -x -y 派生类对象 -z 继承的基类成员 自定义成员 基类对象 派生类对象 is-a 派生类对象用作基类对象时,只使用派生类对象中继承的基类成员x、y 基类对象 派生类对象 is-a  若将基类对象用作派生类对象,基类对象中不存在派生类中自定义的成员z 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(5) 多态性产生的条件1:基类的指针或引用 通过基类的指针或引用调用virtual函数时会产生多态性 二维图形 13.1多态性 继承中指针和对象的关系(5) 通过基类的指针或引用调用virtual函数时会产生多态性 多态性产生的条件1:基类的指针或引用 二维图形 TwoDimensionalShape 圆 Circle 矩形 Rectangle 正方形 Square 利用基类的指针向继承层级中的各个不同类的对象传递消息 is-a 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(6) 利用基类的指针向继承层级中的各个不同类的对象传递消息 13.1多态性 消息 对象类型 Circle Rectangle Square draw pr->draw() Circle circle; Rectangle rectangle; Square sqare; TwoDimensionalShape *pr; pr = &circle; pr->draw(); pr = &rectangle; pr = &sqare; 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(7) 基类(派生类)指针指向基类(派生类)对象 13.1多态性 基类指针 基类对象 派生类对象 派生类指针 指针->成员函数 基类对象 派生类对象 数据段 基类的成员函数 派生类的成员函数 代码段 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(8) 基类指针指向派生类对象 句柄:决定调用哪个类的成员函数 对象:决定操作哪个对象的数据 句柄函数 对象数据 13.1多态性 继承中指针和对象的关系(8) 基类指针指向派生类对象 基类指针 派生类对象 指针->成员函数 基类对象 派生类对象 数据段 基类的成员函数 派生类的成员函数 代码段 句柄:决定调用哪个类的成员函数 对象:决定操作哪个对象的数据 句柄函数 对象数据 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(9) 基类指针调用派生类成员函数 13.1多态性 继承中指针和对象的关系(9) 基类指针调用派生类成员函数 基类指针只允许调用基类的成员函数,不允许调用派生 类定义的成员函数,否则会引起编译错误 若基类指针指向派生类对象,则通过向下强制类型转换 (downcasting),强制将基类指针转换为派生类指针后, 才可以访问派生类定义的成员 基类对象a -x -getX() 派生类对象b -z -getZ() A a; B b; A *p = &b; p->getX(); //ok p->getZ(); //error staic_cast<B *>(p); p->getZ(); //ok 东南大学计算机学院 11/11/2018

继承中指针和对象的关系(10) 多态性的要求 不能产生多态性! virtual函数 同样的消息在发送给不同的对象时会产生多种形式的结果 13.1多态性 继承中指针和对象的关系(10) 多态性的要求 同样的消息在发送给不同的对象时会产生多种形式的结果 TwoDimensionalShape::draw(){cout<<*;} 消息 对象类型 响应 Circle Rectangle Square draw 期望的响应 * pr->draw() 不能产生多态性! virtual函数 东南大学计算机学院 11/11/2018

virtual函数(1) virtual函数 virtual函数指示根据句柄指向的对象的类型调用与之相应的virtual函数版本 句柄函数 13.1多态性 virtual函数(1) virtual函数 关键概念 virtual函数指示根据句柄指向的对象的类型调用与之相应的virtual函数版本 句柄函数 对象数据 非virtual函数的调用 对象函数 virtual函数的调用 基类指针 派生类对象 A a; //基类 B b; //派生类 A *p = &b; //若f()为virtual函数 p->f(); //调用B::f() 东南大学计算机学院 11/11/2018

virtual函数(2) virtual函数定义和重写 关于派生类中重写virtual函数 重写VS.重定义 13.1多态性 virtual函数(2) virtual函数定义和重写 在基类中声明为virtual函数 在派生类中重写 关于派生类中重写virtual函数 函数原型(函数名和返回类型)不能改变 virtual关键字可以省略,但是最好保留(程序更加清晰) 不重写,则派生类直接继承它在基类中的实现 重写VS.重定义 基类函数声明为virtual  重写 基类函数未声明为virtual  重定义 virtual void draw(); 东南大学计算机学院 11/11/2018

virtual函数(3) virtual函数具有传递性 二维图形 TwoDimensionalShape 矩形 圆 Rectangle 13.1多态性 virtual函数(3) virtual函数具有传递性 virtual void draw(); 二维图形 TwoDimensionalShape 圆 Circle 矩形 Rectangle 正方形 Square void draw(); 仍为virtual函数 是重写,不是重定义 东南大学计算机学院 11/11/2018

virtual函数(4) 多态性! 多态性产生的条件 通过基类的指针或引用调用virtual函数时 13.1多态性 消息 对象类型 响应 virtual void draw(); 消息 对象类型 响应 Circle Rectangle Square draw pr->draw() 多态性! 多态性产生的条件 通过基类的指针或引用调用virtual函数时 二者缺一不可 东南大学计算机学院 11/11/2018

virtual函数与动态绑定(1) 静态绑定(static binding): 动态绑定(dynamic/late binding): 13.1多态性 virtual函数与动态绑定(1) 静态绑定(static binding): 动态绑定(dynamic/late binding): 在编译时确定调用哪个函数 关键概念 在运行时确定调用哪个函数 静态 编译时 一般变量 一般数组 动态 运行时 动态变量 动态数组 VS. 绑定:确定调用哪个函数,即,绑定函数及其操作的对象 东南大学计算机学院 11/11/2018

virtual函数与动态绑定(2) virtual函数的绑定方式 通过对象名调用:静态绑定(调用该类定义的函数) 13.1多态性 virtual函数与动态绑定(2) virtual函数的绑定方式 通过对象名调用:静态绑定(调用该类定义的函数) 通过对象的指针调用:动态绑定 通过对象的引用调用:动态绑定 使用virtual函数进行动态绑定,只能通过指针或引用完成 东南大学计算机学院 11/11/2018

为何需要多态性?(1) 多态性使类用户能专注于普遍性问题,而从对各种不同派 生类的特性的细节的关注中解脱出来 13.1多态性 为何需要多态性?(1) 多态性使类用户能专注于普遍性问题,而从对各种不同派 生类的特性的细节的关注中解脱出来 运行环境自己根据对象类型选择相应的行为 只要类在继承层次中,类客户只需关心基类,甚至不需 知道具体类,即可执行与类对象相应的行为 消息 对象类型 响应 Circle Rectangle Square draw pr->draw() 东南大学计算机学院 11/11/2018

为何需要多态性?(2) 类用户可以用与接受消息的对象类型无关的方式编写, 因此提高了软件的可扩展性 二维图形 13.1多态性 为何需要多态性?(2) 类用户可以用与接受消息的对象类型无关的方式编写, 因此提高了软件的可扩展性 二维图形 TwoDimensionalShape 圆 Circle 矩形 Rectangle 正方形 Square 消息 对象类型 响应 Circle Rectangle Square draw Ring 环 Ring pr->draw() 无需改变 东南大学计算机学院 11/11/2018

多态性实例

多态性实例 非virtual函数方式实现 VS. virtual函数方式实现 佣金雇员 CommissionEmployee 带底薪佣金雇员 13.2多态性实例 多态性实例 非virtual函数方式实现 VS. virtual函数方式实现 佣金雇员 CommissionEmployee 带底薪佣金雇员 BasePlusCommissionEmployee 消息 响应 Commission Employee BasePlusCommissionEmployee earnings 对象类型 grossSales×commissionRate baseSalary + grossSales×commissionRate 东南大学计算机学院 11/11/2018

非virtual函数方式实现(1) CommissionEmployee类 BasePlusCommissionEmployee类 13.2多态性实例 非virtual函数方式实现(1) CommissionEmployee类 类定义(Fig. 13.1) 类实现(Fig. 13.2) BasePlusCommissionEmployee类 类定义(Fig. 13.4) 类实现(Fig. 13.5) 东南大学计算机学院 11/11/2018

非virtual函数方式实现(2) 13.2多态性实例 Fig. 13.5: fig13_05.cpp …… 16 int main() ……    16 int main()    17 {    18    // create base-class object    19    CommissionEmployee commissionEmployee(    20       "Sue", "Jones", "222-22-2222", 10000, .06 );    21     22    // create base-class pointer    23    CommissionEmployee *commissionEmployeePtr = 0;    24     25    // create derived-class object    26    BasePlusCommissionEmployee basePlusCommissionEmployee(    27       "Bob", "Lewis", "333-33-3333", 5000, .04, 300 );    28     29    // create derived-class pointer    30    BasePlusCommissionEmployee *basePlusCommissionEmployeePtr = 0;

非virtual函数方式实现(3) 13.2多态性实例 通过函数名调用, 静态绑定 Fig. 13.5: fig13_05.cpp …… ……       35 // output objects commissionEmployee and basePlusCommissionEmployee    36 cout << "Print base-class and derived-class objects:\n\n";    37 commissionEmployee.print(); // invokes base-class print    38 cout << "\n\n";    39 basePlusCommissionEmployee.print(); // invokes derived-class print Print base-class and derived-class objects: commission employee: Sue Jones social security number: 222-22-2222 gross sales: 10000.00 commission rate: 0.06 base-salaried commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 base salary: 300.00 通过函数名调用, 静态绑定

基类指针指向基类对象, 静态绑定 派生类指针指向派生类对象, 静态绑定 Fig. 13.5: fig13_05.cpp   41 // aim base-class pointer at base-class object and print    42 commissionEmployeePtr = &commissionEmployee; // perfectly natural    43 cout << "\n\n\nCalling print with base-class pointer to "    44    << "\nbase-class object invokes base-class print function:\n\n";    45 commissionEmployeePtr->print(); // invokes base-class print    46     47 // aim derived-class pointer at derived-class object and print    48 basePlusCommissionEmployeePtr = &basePlusCommissionEmployee; // natural    49 cout << "\n\n\nCalling print with derived-class pointer to "    50    << "\nderived-class object invokes derived-class "    51    << "print function:\n\n";    52 basePlusCommissionEmployeePtr->print(); // invokes derived-class print 基类指针指向基类对象, 静态绑定 派生类指针指向派生类对象, 静态绑定 commission employee: Sue Jones social security number: 222-22-2222 gross sales: 10000.00 commission rate: 0.06 base-salaried commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 base salary: 300.00

非virtual函数方式实现(5) 13.2多态性实例 基类指针指向派生类对象, 静态绑定 函数:基类的print() Fig. 13.5: fig13_05.cpp   54 // aim base-class pointer at derived-class object and print    55 commissionEmployeePtr = &basePlusCommissionEmployee;    56 cout << "\n\n\nCalling print with base-class pointer to "    57    << "derived-class object\ninvokes base-class print "    58    << "function on that derived-class object:\n\n";    59 commissionEmployeePtr->print(); // invokes base-class print    60 cout << endl; 基类指针指向派生类对象, 静态绑定 函数:基类的print() 数据: basePlusCommissionEmployee的数据 若此处: commissionEmployeePtr->earnings (); 结果? commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 5000 * 0.04 = 200 注意:没有baseSalary

非virtual函数方式实现(6) 13.2多态性实例 错误 不可将派生类指针指向基类对象, 基类对象不是一个(is-a)派生类对象 Fig. 13.6: fig13_06.cpp    6 int main()     7 {     8    CommissionEmployee commissionEmployee(     9       "Sue", "Jones", "222-22-2222", 10000, .06 );    10    BasePlusCommissionEmployee *basePlusCommissionEmployeePtr = 0;    11     12    // aim derived-class pointer at base-class object    13    // Error: a CommissionEmployee is not a BasePlusCommissionEmployee    14    basePlusCommissionEmployeePtr = &commissionEmployee;    15    return 0;    16 } // end main 错误 不可将派生类指针指向基类对象, 基类对象不是一个(is-a)派生类对象

非virtual函数方式实现(7) 13.2多态性实例 OK, 基类的函数 错误, 派生类的函数 Fig. 13.6: fig13_06.cpp    7 int main()     8 {     9    CommissionEmployee *commissionEmployeePtr = 0; // base class    10    BasePlusCommissionEmployee basePlusCommissionEmployee(    11       "Bob", "Lewis", "333-33-3333", 5000, .04, 300 ); // derived class    12     14    commissionEmployeePtr = &basePlusCommissionEmployee;    15     18    string firstName = commissionEmployeePtr->getFirstName();    19    string lastName = commissionEmployeePtr->getLastName();    20    string ssn = commissionEmployeePtr->getSocialSecurityNumber();    21    double grossSales = commissionEmployeePtr->getGrossSales();    22    double commissionRate = commissionEmployeePtr->getCommissionRate();    23     26    double baseSalary = commissionEmployeePtr->getBaseSalary();    27    commissionEmployeePtr->setBaseSalary( 500 );    28    return 0;    29 } // end main OK, 基类的函数 错误, 派生类的函数

virtual函数方式实现(1) 13.2多态性实例 virtual函数, 动态绑定 9 class CommissionEmployee    10 {    11 public:    12    CommissionEmployee( const string &, const string &, const string &,    13       double = 0.0, double = 0.0 );    14     15    void setFirstName( const string & ); // set first name    16    string getFirstName() const; // return first name    17     …….    30    virtual double earnings() const; // calculate earnings    31    virtual void print() const; // print CommissionEmployee object    32 private:    33    string firstName;    34    string lastName;    35    string socialSecurityNumber;    36    double grossSales; // gross weekly sales    37    double commissionRate; // commission percentage    38 }; // end class CommissionEmployee Fig. 13.8: CommissionEmployee.h virtual函数, 动态绑定 东南大学计算机学院 11/11/2018

virtual函数方式实现(2) 13.2多态性实例 virtual函数, 基类函数的重写 13.9: BasePlusCommissionEmployee.h    10 #include "CommissionEmployee.h" // CommissionEmployee class declaration    11     12 class BasePlusCommissionEmployee : public CommissionEmployee    13 {    14 public:    15    BasePlusCommissionEmployee( const string &, const string &,    16       const string &, double = 0.0, double = 0.0, double = 0.0 );    17     18    void setBaseSalary( double ); // set base salary    19    double getBaseSalary() const; // return base salary    20     21    virtual double earnings() const; // calculate earnings    22    virtual void print() const; // print BasePlusCommissionEmployee object    23 private:    24    double baseSalary; // base salary    25 }; // end class BasePlusCommissionEmployee virtual函数, 基类函数的重写 东南大学计算机学院 11/11/2018

virtual函数方式实现(3) 13.2多态性实例 基类指针指向基类对象, 动态绑定 函数: 基类的print() Fig. 13.10: fig13_10.cpp    45 // aim base-class pointer at base-class object and print    46 commissionEmployeePtr = &commissionEmployee;    47 cout << "\n\nCalling virtual function print with base-class pointer"    48    << "\nto base-class object invokes base-class "    49    << "print function:\n\n";    50 commissionEmployeePtr->print(); // invokes base-class print 基类指针指向基类对象, 动态绑定 函数: 基类的print() 数据: commissionEmployee的数据 若此处: commissionEmployeePtr->earnings (); 结果? commission employee: Sue Jones social security number: 222-22-2222 gross sales: 10000.00 commission rate: 0.06 10000 * 0.06 = 600

virtual函数方式实现(4) 13.2多态性实例 基类指针指向派生类对象, 动态绑定 函数: 派生类的print() Fig. 13.10: fig13_10.cpp   59 // aim base-class pointer at derived-class object and print    60  commissionEmployeePtr = &basePlusCommissionEmployee;    61  cout << "\n\nCalling virtual function print with base-class pointer"    62     << "\nto derived-class object invokes derived-class "    63     << "print function:\n\n";    64     67  commissionEmployeePtr->print(); 基类指针指向派生类对象, 动态绑定 函数: 派生类的print() 数据: basePlusCommissionEmployee的数据 若此处: commissionEmployeePtr->earnings (); 结果? base-salaried commission employee: Bob Lewis social security number: 333-33-3333 gross sales: 5000.00 commission rate: 0.04 base salary: 300.00 300 + 5000 * 0.04 = 500 注意:有baseSalary

抽象类和纯virtual函数 抽象类和具体类 抽象类和纯virtual函数

抽象类和具体类(1) 根据是否实例化对象 具体类(concrete class):可以实例化对象 13.3抽象类和具体类 抽象类和具体类(1) 根据是否实例化对象 具体类(concrete class):可以实例化对象 抽象类(abstract class):不能实例化对象 二维图形 TwoDimensionalShape 圆 Circle 矩形 Rectangle 正方形 Square 环 Ring 抽象类 (抽象基类) 具体类 具体类 具体类 具体类 东南大学计算机学院 11/11/2018

ThreeDimensionalShape 13.3抽象类和具体类 抽象类和具体类(2) 二维图形 TwoDimensionalShape 圆 Circle 矩形 Rectangle 正方形 Square 环 Ring 图形 Shape 三维图形 ThreeDimensionalShape 球 Sphere 立方体Cube 抽象类 (抽象基类) 抽象类 抽象类 具体类 具体类 具体类 具体类 具体类 具体类 抽象类为其派生类定义了公共的通用接口 东南大学计算机学院 11/11/2018

virtual void draw() const = 0; 13.3抽象类和具体类 抽象类和纯virtual函数(1) 如何定义抽象类 纯virtual函数 不提供virtual函数的具体实现 纯virtual函数是不完整的 派生的具体类必须重写所有基类的纯virtual函数的定义 至少声明一个virtual函数为纯virtual函数(pure virtual function) virtual void draw() const = 0; pure specifier 可包含数据成员和具体的成员函数 东南大学计算机学院 11/11/2018

抽象类和纯virtual函数(2) virutal函数 VS. 纯virtual函数 virtual函数 纯virtual函数 函数实现 有 13.3抽象类和具体类 抽象类和纯virtual函数(2) virutal函数 VS. 纯virtual函数 virtual函数 纯virtual函数 函数实现 有 没有 类的种类 具体类 抽象类 类定义 完整 不完整 派生类中重写 重写 不重写直接继承 重写具体类 不重写抽象类 东南大学计算机学院 11/11/2018

实例研究:工资发放系统 继承层次 实现

BasePlusCommissionEmployee 13.4实例研究 继承层次(1) 分析:数据成员 雇员 Employee 薪金雇员 SalariedEmployee 佣金雇员 CommissionEmployee 钟点雇员 HourlyEmployee 带底薪佣金雇员 BasePlusCommissionEmployee first name, last name, social security number first name, last name, social security number, salary first name, last name, social security number, hours, wage first name, last name, social security number, commission rate, gross sales first name, last name, social security number, commission rate, gross sales, base salary 东南大学计算机学院 11/11/2018

13.4实例研究 继承层次(2) 分析: 成员函数 东南大学计算机学院 11/11/2018

BasePlusCommissionEmployee 13.4实例研究 继承层次(3) 第1步:确定根类 第2步:确定派生类中需要增加的成员 CommissionEmployee -commissionRate -grossSales SalariedEmployee -salary HourlyEmployee -hours -wage BasePlusCommissionEmployee -baseSalary Employee -fistName -lastName -socialSecurityNumber -earnings() -print()

BasePlusCommissionEmployee 13.4实例研究 继承层次(4) 第3步:确定派生类间的继承关系 Employee -fistName -lastName -socialSecurityNumber -earnings() -print() CommissionEmployee -commissionRate -grossSales SalariedEmployee -salary HourlyEmployee -hours -wage BasePlusCommissionEmployee -baseSalary

BasePlusCommissionEmployee 13.4实例研究 继承层次(5) 雇员 Employee 薪金雇员 SalariedEmployee 佣金雇员 CommissionEmployee 钟点雇员 HourlyEmployee 带底薪佣金雇员 BasePlusCommissionEmployee 东南大学计算机学院 11/11/2018

继承层次(6) 第4步: 确定纯virtual函数 和virtual函数, 并确定: 抽象类和具体类 -earnings()为 13.4实例研究 继承层次(6) 第4步: 确定纯virtual函数 和virtual函数, 并确定: 抽象类和具体类 -earnings()为 纯virtual函数 -print()为 virtual函数 Employee为抽象类 其他类为具体类 东南大学计算机学院 11/11/2018

Fig. 13.13: Employee.h     9 class Employee    10 {    11 public:    12    Employee( const string &, const string &, const string & );    13     14    void setFirstName( const string & ); // set first name    15    string getFirstName() const; // return first name    16     17    void setLastName( const string & ); // set last name    18    string getLastName() const; // return last name    19     20    void setSocialSecurityNumber( const string & ); // set SSN    21    string getSocialSecurityNumber() const; // return SSN    22     23    // pure virtual function makes Employee abstract base class    24    virtual double earnings() const = 0; // pure virtual    25    virtual void print() const; // virtual    26 private:    27    string firstName;    28    string lastName;    29    string socialSecurityNumber;    30 }; // end class Employee 根类定义,抽象基类 cpp文件中不包含earnings()函数的实现

Fig. 13.15: SalariedEmployee.h     8 class SalariedEmployee : public Employee     9 {    10 public:    11    SalariedEmployee( const string &, const string &,    12       const string &, double = 0.0 );    13     14    void setWeeklySalary( double ); // set weekly salary    15    double getWeeklySalary() const; // return weekly salary    16     17    // keyword virtual signals intent to override    18    virtual double earnings() const; // calculate earnings    19    virtual void print() const; // print SalariedEmployee object    20 private:    21    double weeklySalary; // salary per week    22 }; // end class SalariedEmployee 派生类定义,具体类    30 double SalariedEmployee::earnings() const    31 {    32    return getWeeklySalary();    33 } // end function earnings    Fig. 13.16: SalariedEmployee.cpp 必须重写earnings()函数

Fig. 13.17: HourlyEmployee.h     8 class HourlyEmployee : public Employee     9 {    10 public:    11    HourlyEmployee( const string &, const string &,    12       const string &, double = 0.0, double = 0.0 );    13     14    void setWage( double ); // set hourly wage    15    double getWage() const; // return hourly wage    16     17    void setHours( double ); // set hours worked    18    double getHours() const; // return hours worked    19     20    // keyword virtual signals intent to override    21    virtual double earnings() const; // calculate earnings    22    virtual void print() const; // print HourlyEmployee object    23 private:    24    double wage; // wage per hour    25    double hours; // hours worked for week    26 }; // end class HourlyEmployee 派生类定义,具体类

Fig. 13.18: HourlyEmployee.cpp    44 double HourlyEmployee::earnings() const    45 {    46    if ( getHours() <= 40 ) // no overtime    47       return getWage() * getHours();    48    else                  49       return 40 * getWage() + ( ( getHours() - 40 ) * getWage() * 1.5 );    50 } // end function earnings 必须重写earnings()函数

    8 class CommissionEmployee : public Employee     9 {    10 public:    11    CommissionEmployee( const string &, const string &,    12       const string &, double = 0.0, double = 0.0 );    13     14    void setCommissionRate( double ); // set commission rate    15    double getCommissionRate() const; // return commission rate    16     17    void setGrossSales( double ); // set gross sales amount    18    double getGrossSales() const; // return gross sales amount    19     20    // keyword virtual signals intent to override    21    virtual double earnings() const; // calculate earnings    22    virtual void print() const; // print CommissionEmployee object    23 private:    24    double grossSales; // gross weekly sales    25    double commissionRate; // commission percentage    26 }; // end class CommissionEmployee Fig. 13.19: CommissionEmployee.h 派生类定义,具体类    43 double CommissionEmployee::earnings() const    44 {    45    return getCommissionRate() * getGrossSales();    46 } // end function earnings 必须重写earnings()函数 Fig. 13.20: CommissionEmployee.cpp

Fig. 13.21: BasePlusCommissionEmployee.h     8 class BasePlusCommissionEmployee : public CommissionEmployee     9 {    10 public:    11    BasePlusCommissionEmployee( const string &, const string &,    12       const string &, double = 0.0, double = 0.0, double = 0.0 );    13     14    void setBaseSalary( double ); // set base salary    15    double getBaseSalary() const; // return base salary    16     17    // keyword virtual signals intent to override    18    virtual double earnings() const; // calculate earnings    19    virtual void print() const; // print BasePlusCommissionEmployee object    20 private:    21    double baseSalary; // base salary per week    22 }; // end class BasePlusCommissionEmployee 间接派生类定义,具体类    32 double BasePlusCommissionEmployee::earnings() const    33 {    34     return getBaseSalary() + CommissionEmployee::earnings();    35 } // end function earnings Fig. 13.22: BasePlusCommissionEmployee.cpp

Polymorphism 教学要求与安排 教学要求 13.7~13.9不要求 东南大学计算机学院 11/11/2018

作业 deadline: 5.19 24:00 H7: Ex. 13.12, 13.16 deadline: 5.24 24:00 东南大学计算机学院 11/11/2018