C++ Programming Lecture 17 Wei Liu ( 刘 威 ) Dept. of Electronics and Information Eng. Huazhong University of Science and Technology May. 2015
Lecture 17 Chapter 20. Object-Oriented Programming: Inheritance 20.1 Introduction 20.2 Base Classes and Derived Classes 20.3 protected Members 20.4 Relationship between Base Classes and Derived Classes 20.5 Constructors and Destructors in Derived Classes 20.6 public, protected and private Inheritance 20.7 Software Engineering with Inheritance -2-
20.1 Introduction Inheritance is a form of software reuse in which you create a class that absorbs an existing class s data and behaviors and enhances them with new capabilities. You can designate that the new class should inherit the members of an existing class. 继 承 是 一 种 软 件 重 用 的 方 式 如 果 现 有 类 可 以 描 述 事 物 的 现 有 数 据 和 行 为, 通 过 继 承 来 获 得 和 增 强 类 的 能 力 This existing class is called the base class, and the new class is referred to as the derived class. 现 有 的 类 被 称 为 基 类, 从 基 类 继 承 出 来 的 类 被 称 为 派 生 类 -3-
Lecture 17 Chapter 20. Object-Oriented Programming: Inheritance 20.1 Introduction 20.2 Base Classes and Derived Classes 20.3 protected Members 20.4 Relationship between Base Classes and Derived Classes 20.5 Constructors and Destructors in Derived Classes 20.6 public, protected and private Inheritance 20.7 Software Engineering with Inheritance -4-
20.2 Base Classes and Derived Classes 现 实 世 界 的 继 承 从 先 辈 处 获 得 属 性 和 行 为 特 征 C++ 中 类 的 继 承 继 承 : 新 的 类 从 已 有 类 那 里 得 到 已 有 的 特 性 派 生 : 从 已 有 类 产 生 新 类 的 过 程 单 继 承 : 一 个 派 生 类 只 有 一 个 直 接 基 类 多 继 承 : 一 个 派 生 类 同 时 有 多 个 基 类 -5-
-6-
20.2 Base Classes and Derived Classes 派 生 类 生 成 的 过 程 吸 收 已 有 的 基 类 的 成 员 构 造 函 数 析 构 函 数 除 外 改 造 基 类 的 成 员 声 明 同 名 的 成 员 后, 隐 藏 了 原 基 类 的 成 员 添 加 新 的 成 员 -7-
20.2 Protected Members C++ 中 类 的 成 员 的 访 问 控 制 属 性 public: 公 有 的 在 该 类 中 直 接 访 问 在 该 类 以 外, 可 以 通 过 该 类 的 名 字 引 用 或 者 指 针 访 问 private: 私 有 的 在 该 类 中 直 接 访 问 在 该 类 以 外, 只 能 通 过 该 类 的 友 元 来 访 问 protected: 保 护 的 在 该 类 中 直 接 访 问 在 该 类 以 外, 可 以 通 过 该 类 的 派 生 类 该 类 的 友 元 访 问 -8-
Lecture 17 Chapter 20. Object-Oriented Programming: Inheritance 20.1 Introduction 20.2 Base Classes and Derived Classes 20.3 protected Members 20.4 Relationship between Base Classes and Derived Classes 20.5 Constructors and Destructors in Derived Classes 20.6 public, protected and private Inheritance 20.7 Software Engineering with Inheritance -9-
20.4.3 创 建 CommissionEmployee 和 BasePlusCommissionEmployee 继 承 结 构 CommissionEmployee - string firstname; - string lastname; - string socialsecuritynumber; - double grosssales; - double commissionrate; + CommissionEmployee(const string &, const string &, double, double) + void setfirstname(const string &); + string getfirstname() const; + double earnings() const; + void print() const; BasePlusCommissionEmployee - string firstname; - string lastname; - string socialsecuritynumber; - double grosssales; - double commissionrate; - double basesalary; + CommissionEmployee(const string &, const string &, double, double, double) + void setfirstname(const string &); + string getfirstname() const; + void setbasesalary (const double &); + double getbasesalary() const; + double earnings() const; + void print() const; 继 承 的 好 处 : 避 免 了 对 同 样 功 能 的 代 码 的 复 制 - 粘 贴, 有 利 于 代 码 的 维 护 -10-
派 生 类 修 改 了 基 类 的 计 算 部 分 派 生 类 新 增 了 对 派 生 数 据 成 员 的 操 作 -11-
20.4.4 使 用 protected 数 据 的 CommissionEmployee BasePlusCommissionEmployee 继 承 结 构 CommissionEmployee - string firstname; - string lastname; - string socialsecuritynumber; - double grosssales; - double commissionrate; + CommissionEmployee(const string &, const string &, double, double) + void setfirstname(const string &); + string getfirstname() const; CommissionEmployee # string firstname; # string lastname; # string socialsecuritynumber; # double grosssales; # double commissionrate; + CommissionEmployee(const string &, const string &, double, double) + void setfirstname(const string &); + string getfirstname() const; 为 了 在 派 生 类 中, 便 于 使 用 从 基 类 继 承 的 数 据 成 员, 可 以 在 基 类 中, 将 这 些 数 据 成 员 声 明 为 保 护 的 数 据 成 员 -12-
当 基 类 的 数 据 成 员 声 明 为 protected 时 : 派 生 类 的 对 象 基 类 的 对 象 私 有 数 据 当 基 类 的 数 据 成 员 声 明 为 private 时 : 派 生 类 的 对 象 基 类 的 公 共 接 口 成 员 函 数 基 类 的 对 象 私 有 数 据 绕 过 了 基 类 的 公 共 接 口 函 数, 有 可 能 破 坏 了 基 类 的 数 据 维 护 关 系, 使 得 基 类 对 象 的 数 据 处 于 不 一 致 的 状 态 因 此 更 好 的 选 择 是 将 基 类 的 数 据 成 员 声 明 为 private -13-
20.4.5 使 用 private 数 据 的 CommissionEmployee BasePlusCommissionEmployee 继 承 结 构 CommissionEmployee # string firstname; # string lastname; # string socialsecuritynumber; # double grosssales; # double commissionrate; + CommissionEmployee(const string &, const string &, double, double) + void setfirstname(const string &); + string getfirstname() const; CommissionEmployee - string firstname; - string lastname; - string socialsecuritynumber; - double grosssales; - double commissionrate; + CommissionEmployee(const string &, const string &, double, double) + void setfirstname(const string &); + string getfirstname() const; 更 好 的 选 择 是 将 基 类 的 数 据 成 员 声 明 为 private, 通 过 基 类 的 公 共 接 口 函 数 对 这 些 数 据 成 员 进 行 访 问 -14-
Lecture 17 Chapter 20. Object-Oriented Programming: Inheritance 20.1 Introduction 20.2 Base Classes and Derived Classes 20.3 protected Members 20.4 Relationship between Base Classes and Derived Classes 20.5 Constructors and Destructors in Derived Classes 20.6 public, protected and private Inheritance 20.7 Software Engineering with Inheritance -15-
20.5 Constructors and Destructors in Derived Classes 基 类 的 构 造 函 数 和 析 构 函 数 不 能 被 继 承 派 生 类 的 构 造 函 数 如 果 派 生 类 没 有 新 增 数 据 成 员 系 统 缺 省 会 调 用 基 类 的 构 造 函 数 和 析 构 函 数 来 处 理 如 果 派 生 类 有 新 增 的 数 据 成 员 新 增 成 员 的 初 始 化 需 要 由 派 生 类 的 构 造 函 数 完 成 原 基 类 成 员 的 初 始 化 通 过 调 用 基 类 的 构 造 函 数 完 成 注 意 : 对 派 生 类 中 新 增 成 员 对 象 的 初 始 化, 调 用 顺 序 按 照 他 们 在 类 中 声 明 的 顺 序 派 生 类 的 析 构 函 数 做 好 新 增 的 数 据 成 员 的 清 理 工 作, 系 统 会 自 动 调 用 原 基 类 的 析 构 函 数 清 理 原 基 类 成 员 -16-
20.6 public, protected and private Inheritance C++ 中 类 的 继 承 方 式 public: 公 有 继 承 基 类 的 公 有 成 员 和 保 护 成 员 的 访 问 属 性 不 变 基 类 的 私 有 成 员 不 可 直 接 访 问 protected: 保 护 继 承 基 类 的 公 有 成 员 和 保 护 成 员 都 以 保 护 成 员 身 份 在 派 生 类 基 类 的 私 有 成 员 不 可 直 接 访 问 private: 私 有 继 承 基 类 的 公 有 成 员 和 保 护 成 员 都 以 私 有 成 员 身 份 在 派 生 类 基 类 的 私 有 成 员 不 可 直 接 访 问 在 实 际 中 建 议 : 做 好 基 类 的 成 员 访 问 的 限 定, 通 过 公 有 继 承 来 派 生 新 的 类 -17-
继 承 的 案 例 : 学 生 研 究 生 基 类 是 本 科 生, 派 生 类 是 研 究 生 派 生 类 吸 收 已 有 的 基 类 的 成 员 构 造 函 数 析 构 函 数 除 外 派 生 类 改 造 基 类 的 成 员 声 明 同 名 的 成 员 后, 隐 藏 了 原 基 类 的 成 员 派 生 类 添 加 新 的 成 员 Student 学 生 Graduate 研 究 生 Student + int id; + string name; + float score; - char gender; + Student() + display() Graduate + int id; + string name; + float score; - char gender; - float pay; + Graduate() + display() 吸 收 已 有 的 基 类 成 员 添 加 新 的 成 员 改 造 基 类 的 成 员 -18-
Class of student : student.h 公 共 的 成 员, 可 以 被 类 以 外 直 接 访 问 保 护 的 成 员, 可 以 被 该 类 的 派 生 类 的 成 员 或 者 友 元 访 问 私 有 的 成 员, 只 能 通 过 友 元 或 者 公 共 接 口 来 访 问 -19-
Class of student : studend.cpp -20-
Class of graduate: graduate.h 表 示 继 承 Student 类 的 所 有 公 共 属 性 派 生 类 可 以 创 建 新 的 数 据 成 员 新 的 成 员 函 数 改 写 基 类 的 成 员 函 数 基 类 的 其 它 数 据 成 员 和 成 员 函 数 都 自 动 的 可 以 被 派 生 类 访 问 -21-
Class of graduate: graduate.cpp 派 生 类 访 问 基 类 的 成 员 函 数 需 要 用 域 说 明 符 :: -22-
Using inheritance 基 类 的 私 有 数 据 实 际 上 也 被 继 承 了, 但 是 不 允 许 派 生 类 直 接 访 问 -23-
Advanced programming (1) Default arguments in constructor Calling parent constructor in child class 派 生 类 不 必 使 用 基 类 的 全 部 数 据 成 员 -24-
Advanced programming (2) Visiting protected / private data members of parent class 派 生 类 不 能 访 问 基 类 的 私 有 数 据 成 员 派 生 类 可 以 通 过 访 问 基 类 的 公 共 成 员 函 数 来 间 接 获 取 私 有 数 据 成 员 的 值 -25-
Lecture 17 Chapter 20. Object-Oriented Programming: Inheritance 20.1 Introduction 20.2 Base Classes and Derived Classes 20.3 protected Members 20.4 Relationship between Base Classes and Derived Classes 20.5 Constructors and Destructors in Derived Classes 20.6 public, protected and private Inheritance 20.7 Software Engineering with Inheritance -26-
面 向 对 象 的 软 件 开 发 面 向 对 象 的 软 件 开 发 方 法 从 分 析 问 题 模 型 开 始, 识 别 出 对 象 对 对 象 的 特 征 进 行 抽 象, 获 得 类 最 后 用 程 序 语 言 去 描 述 他 们 的 过 程 程 序 更 加 关 心 对 象 与 对 象 之 间 的 关 系 面 向 过 程 的 开 发 面 向 对 象 的 开 发 如 何 编 码 实 现 过 程 如 何 分 析 对 象 关 系 以 功 能 实 现 为 中 心 以 数 据 操 作 为 中 心 -27-
对 象 与 对 象 的 关 系 对 象 之 间 有 两 种 关 系 : 复 合, 继 承 对 象 的 复 合 对 象 A 包 含 对 象 B, 拥 有,has-a 对 象 的 继 承 对 象 A 是 对 象 B 的 一 个 特 例, 是,is-a 类 的 设 计 如 果 新 的 类 中 有 成 员 是 已 有 的 类 的 对 象, 使 用 复 合 方 式 比 较 合 适 如 果 新 的 类 可 以 视 为 已 有 类 的 子 类 或 者 特 例, 使 用 继 承 比 较 合 适 -28-
面 向 对 象 的 分 析 案 例 点 线 段 多 边 形 线 段 包 括 两 个 顶 点 ; 线 段 的 运 算 是 计 算 线 段 的 长 度 多 边 形 包 括 多 个 线 段 ; 多 边 形 的 运 算 是 获 得 多 边 形 的 周 长 三 角 形 三 角 形 包 括 三 个 线 段, 是 多 边 形 的 特 例, 三 角 形 的 典 型 运 算 是 获 得 其 面 积 -29-
面 向 对 象 的 分 析 案 例 Point 点 - double x; - double y; + Point(double,double); + void setpoint(double, double); + double getx(); + double gety(); 1 1 -startpoint 1 - endpoint 1 Line 线 段 - Point startpoint; - Point endpoint; + Line(point, point); + void setline(point, point); + Point getstart (); + Point getend(); + double getlength(); 思 考 : 这 两 个 类 是 什 么 关 系? 在 Line 类 中 是 否 需 要 设 置 数 据 成 员 length? 在 Line 类 中 是 否 需 要 设 置 输 入 四 个 坐 标 值 的 setline 函 数? -30-
面 向 对 象 的 分 析 案 例 Line 线 段 - borders Polygon 多 边 形 - Point startpoint; - Point endpoint; 1 1.* - Line borders[]; - int number; + Line(point, point); + void setline(point, point); + Point getstart(); + Point getend(); + double getlength(); + Polygon(Point[], int); + void setpolygon(point[], int); + int getnumber(); + double getperimeter(); #define MAX_BORDER_NUM 6 思 考 : 这 两 个 类 是 什 么 关 系? 在 Polygon 类 中 需 要 设 置 Point 类 型 的 数 据 成 员? 在 Polygon 类 能 否 支 持 动 态 数 量 的 边 长 数 组? 在 Polygon 类 中 能 否 加 上 对 形 状 的 判 别? -31-
面 向 对 象 的 分 析 案 例 Polygon 多 边 形 - Line borders[]; - int number; + Polygon(Point[], int); + void setpolygon(point[], int); + int getnumber(); + double getperimeter(); Triangle 三 角 形 + double getarea(); 思 考 : 这 两 个 类 是 什 么 关 系? 在 Trianlge 类 中 还 需 要 其 他 的 数 据 成 员 吗? 在 Trianlge 类 中 能 否 加 上 对 形 状 的 判 别? -32-
Experiment 实 现 前 述 提 到 的 几 个 类, 分 别 实 现 其 头 文 件 h 文 件 和 源 文 件 cpp 文 件, 利 用 继 承 简 化 类 的 实 现, 测 试 你 的 类 是 否 有 效 -33-
谢 谢! 刘 威 副 教 授 互 联 网 技 术 与 工 程 研 究 中 心 华 中 科 技 大 学 电 子 与 信 息 工 程 系 Email: liuwei@hust.edu.cn 网 址 :http://itec.hust.edu.cn