资源描述
第 5章 多 态 性 与 虚 函 数n本 章 的 学 习 目 的 客 观 世 界 中 的 事 物 多 种 多 样 、 千 姿 百 态 , 各 类 事物 都 有 其 特 殊 性 , 这 就 是 客 观 世 界 的 多 态 性 。 为 了正 确 反 映 客 观 世 界 的 多 态 性 , 面 向 对 象 技 术 中 也 提供 了 多 态 性 机 制 , 使 多 态 性 成 为 了 面 向 对 象 程 序 设计 的 重 要 特 征 。 所 谓 多 态 性 就 是 在 类 层 次 结 构 的 相同 类 或 不 同 类 中 , 可 用 相 同 的 函 数 名 实 现 功 能 不 同的 操 作 。 多 态 性 的 应 用 使 编 程 更 为 简 捷 、 便 利 , 它为 程 序 的 模 块 化 设 计 提 供 了 又 一 支 持 手 段 。 因 此 , 在 学 过 面 向 对 象 的 封 装 性 和 继 承 性 编 程 机制 之 后 , 我 们 还 应 该 了 解 和 掌 握 多 态 性 编 程 机 制 ,以 提 高 我 们 的 面 向 对 象 编 程 能 力 。 n本 章 的 学 习 内 容 多 态 性 的 概 念 函 数 重 载 运 算 符 重 载 静 态 联 编 和 动 态 联 编 的 概 念 虚 函 数 的 概 念 抽 象 类 的 概 念 5.1 多 态 性 的 概 念 n多 态 性 是 指 在 类 层 次 结 构 的 相 同 类 或 不 同 类 中 ,可 用 相 同 的 函 数 名 实 现 功 能 不 同 的 操 作 , 从 而 可以 使 用 相 同 的 调 用 方 式 来 调 用 这 些 具 有 不 同 功 能的 同 名 函 数 , 例 如 p-display()。nC+的 多 态 性 使 同 一 条 消 息 , 被 不 同 类 型 的 对 象接 收 时 将 产 生 不 同 的 行 为 。n多 态 性 是 实 现 “ 一 种 接 口 , 多 种 方 法 ” 的 技 术 。这 里 的 “ 一 种 接 口 ” 是 指 相 同 函 数 名 , 而 “ 多 种方 法 ” 是 指 多 种 函 数 实 现 。 nC+支 持 的 多 态 可 以 分 为 两 种 类 型 :编 译 时 多 态 : 编 译 系 统 在 编 译 阶 段 就 可 以 根据 调 用 函 数 的 操 作 参 数 来 确 定 调 用 哪 个 同 名函 数 。运 行 时 多 态 : 在 类 的 继 承 层 次 结 构 中 , 不 同层 次 的 类 中 可 能 具 有 同 名 但 实 现 不 同 的 函 数 ,需 要 在 运 行 阶 段 才 能 根 据 对 象 所 属 的 层 次 来确 定 调 用 哪 个 类 中 的 同 名 函 数 。 5.2 联 编n 多 态 性 的 实 现 过 程 中 , 把 一 个 消 息 函 数 ( 如student1.display()与 一 个 对 象 的 具 体 函 数体 相 联 系 的 过 程 叫 做 联 编 ( binding) , 即 确定 调 用 哪 个 对 象 的 哪 个 同 名 函 数 的 过 程 , 又 称绑 定 。n 按 照 联 编 时 所 处 阶 段 的 不 同 , 可 以 把 联 编 分 为静 态 联 编 和 动 态 联 编 , 这 两 种 联 编 过 程 分 别 对应 着 多 态 性 的 两 种 实 现 方 式 。5.2.1 静 态 联 编 在 编 译 阶 段 由 编 译 系 统 根 据 调 用 函 数 的 操 作参 数 来 确 定 调 用 哪 个 同 名 函 数 ,并 将 函 数 调 用与 该 函 数 体 连 接 起 来 . 例 5-1 静 态 联 编 #include class Student public: void print() cout“A student”endl; ;class GStudent:public Student public: void print() cout“A graduate student” print(); ps= ps- print(); A student A graduate student A student A student A student 5.2.2 动 态 联 编n只 有 在 运 行 程 序 时 才 能 根 据 函 数 调 用 指 令 来 确 定将 要 调 用 的 函 数 。 这 种 在 运 行 阶 段 进 行 的 联 编 称为 动 态 联 编 。n动 态 联 编 的 优 点 是 提 供 了 更 好 的 编 程 灵 活 性 、 问题 的 抽 象 性 和 程 序 易 维 护 性 , 缺 点 是 与 静 态 联 编相 比 , 函 数 调 用 速 度 慢 。 ( 如 ps- print(); )n问 题 的 抽 象 性 : 在 实 际 应 用 中 , 编 程 人 员 不 必 过多 地 考 虑 类 的 层 次 关 系 , 无 须 显 式 地 写 出 虚 函 数的 路 径 , 只 需 将 对 象 指 针 指 向 相 应 的 派 生 类 对 象或 引 用 相 应 的 对 象 , 通 过 动 态 联 编 就 可 以 对 消 息做 出 正 确 的 反 应 。 ( 如 ps- print(); ) 5.3 虚 函 数 虚 函 数 是 动 态 联 编 的 基 础 。 虚 函 数 是 非 静 态 的 成 员函 数 , 经 过 派 生 之 后 , 虚 函 数 在 类 族 中 可 以 实 现 运 行时 的 多 态 性 。 5.3.1 虚 函 数 的 声 明 虚 函 数 是 一 个 在 某 基 类 中 用 virtual声 明 的 ,并 在 一个 或 多 个 派 生 类 中 被 重 新 定 义 的 成 员 函 数 。 声 明 虚 函 数的 格 式 如 下 : virtual (); 一 个 函 数 一 旦 声 明 为 虚 函 数 , 则 在 每 层 派 生 类 中 ,该 函 数 都 保 持 虚 函 数 特 性 。 因 此 , 在 派 生 类 中 重 新定 义 该 函 数 时 , 可 以 省 略 关 键 字 virtual。 但 为 了程 序 的 可 读 性 , 往 往 不 省 略 。 5.3.2 虚 函 数 的 使 用n如 果 某 类 中 的 一 个 成 员 函 数 被 说 明 为 虚 函 数 ,这 就 意 味 着 该 成 员 函 数 在 派 生 类 中 可 能 有 不同 的 函 数 实 现 。n当 使 用 对 象 指 针 或 对 象 引 用 调 用 虚 函 数 时 ,就 可 实 现 动 态 联 编 , 即 在 运 行 时 进 行 关 联 或绑 定 。n定 义 一 个 基 类 的 对 象 指 针 就 可 以 指 向 不 同 派生 类 的 对 象 ,来 调 用 不 同 派 生 类 的 虚 函 数 ;(2)只 有 通 过 对 象 指 针 或 对 象 引 用 来 调 用 虚 函 数 ,才 能 实 现 动 态 联 编 。 如 果 采 用 对 象 来 调 用 虚函 数 ,则 采 用 的 仍 然 是 静 态 联 编 方 式 。 例 5-2 静 态 联 编 和 动 态 联 编 #include class Student public: virtual void print() cout“A student”endl; ;class GStudent:public Student public: virtual void print() cout“A graduate student” print(); ps= ps- print(); A student A graduate studentA studentA studentA graduate student 使 用 虚 函 数 时 应 注 意 :( 1) 在 派 生 类 中 重 新 定 义 虚 函 数 时 , 必 须 保 证 函数 的 返 回 值 类 型 和 参 数 与 基 类 中 的 声 明 完 全 一 致 。在 类 的 成 员 函 数 被 声 明 为 虚 函 数 后 , 派 生 类 就 具有 多 态 性 。( 2) 一 般 来 说 , 可 将 类 族 中 的 具 有 共 性 的 成 员 函数 声 明 为 虚 函 数 , 而 具 有 个 性 的 函 数 没 有 必 要 声明 为 虚 函 数 。 如 果 在 派 生 类 中 没 有 重 新 定 义 虚 函数 , 则 派 生 类 的 对 象 将 使 用 基 类 的 虚 函 数 代 码 。 静 态 成 员 函 数 不 能 声 明 为 虚 函 数 。 内 联 成 员 函 数 不 能 声 明 为 虚 函 数 。 因 为 对 于 内联 成 员 函 数 , 在 程 序 编 译 时 , 编 译 系 统 就 应 明 确用 哪 个 函 数 体 替 换 内 联 函 数 调 用 的 地 方 , 而 不 能等 到 运 行 时 再 确 定 调 用 哪 个 函 数 。 构 造 函 数 不 能 是 虚 函 数 。 因 为 构 造 函 数 是 在 对 象产 生 之 前 运 行 的 , 而 虚 函 数 是 使 用 已 有 对 象 来 调用 的 函 数 。 所 以 , 将 构 造 函 数 声 明 为 虚 函 数 是 没有 意 义 的 。 析 构 函 数 可 以 是 虚 函 数 , 且 往 往 被 定 义 成 虚 函 数 。因 为 实 施 多 态 时 是 通 过 将 基 类 的 指 针 指 向 派 生 类的 对 象 来 完 成 的 , 如 果 要 删 除 该 指 针 所 指 的 派 生类 对 象 时 就 应 该 调 用 该 指 针 所 指 向 的 派 生 类 的 析构 函 数 , 然 后 派 生 类 的 析 构 函 数 又 调 用 基 类 的 析构 函 数 , 这 样 整 个 派 生 类 的 对 象 才 能 被 完 全 释 放 。 5.4 抽 象 类n有 时 在 声 明 一 个 基 类 时 无 法 为 虚 函 数 定 义 其 具体 实 现 , 这 时 可 以 将 其 声 明 为 一 个 纯 虚 函 数 。包 含 纯 虚 函 数 的 抽 象 类 。n抽 象 类 是 一 种 特 殊 的 类 , 专 门 作 为 基 类 派 生 新类 , 自 身 无 法 实 例 化 , 也 就 是 无 法 定 义 抽 象 类的 对 象 , 它 为 一 类 族 提 供 统 一 的 操 作 界 面 。n抽 象 类 是 为 了 抽 象 和 设 计 的 目 的 而 建 立 的 , 可以 说 , 建 立 抽 象 类 , 就 是 为 了 通 过 它 多 态 地 使用 其 中 的 成 员 函 数 。n抽 象 类 处 于 类 层 次 的 上 层 , 由 它 派 生 新 类 , 然后 再 实 例 化 。 5.4.1 纯 虚 函 数 的 定 义n 在 C+中 , 一 个 仅 为 多 态 机 制 提 供 一 个 接 口 而 没 有 任何 实 体 定 义 的 函 数 , 被 称 为 纯 虚 函 数 。n 声 明 纯 虚 函 数 的 一 般 格 式 如 下 :n抽 象 类 只 能 用 作 其 他 类 的 基 类 , 不 能 用 来 建 立抽 象 类 对 象 。 抽 象 类 不 能 用 作 参 数 类 型 、 函 数返 回 值 类 型 或 显 式 转 换 的 类 型 , 但 可 以 说 明 或定 义 抽 象 类 的 指 针 或 引 用 , 该 指 针 或 引 用 可 以指 向 抽 象 类 的 派 生 类 对 象 , 进 而 实 现 多 态 性 。virtual ()=0; 例 5-3抽 象 类 的 定 义 和 应 用class Shapes protected: int x,y; public: void setvalue(int d,int w=0) x=d; y=w; virtual void disp()=0; ; class Square:public Shapes public: void disp() cout“area of rectangle:”x*ysetvalue(10,5); ptr-disp(); 程 序 的 运 行 结 果 为 : area of rectangular:50 习 题 和 实 验 题项 目 设 计 1-用 面 向 对 象 方 法 实 现 校 园 信 息 管 理 系 统1 系 统 分 析 和 设 计 校 园 信 息 管 理 系 统 的 主 要 功 能 就 是 对 在 校 人 员 (包 括学 生 和 教 师 )的 信 息 资 料 进 行 管 理 。 虽 然 系 统 有 时 需 要 将 教 师 和 学 生 分 成 两 部 分单 独 管 理 , 但 有 时 也 需 要 将 全 体 人 员 作 为 一 类对 象 进 行 统 一 管 理 , 以 提 高 管 理 效 率 。 系 统 除 了 能 输 入 人 员 信 息 、 查 询 和 分 析 信息 以 外 , 还 应 能 将 数 据 永 久 保 存 到 磁 盘 中 , 以免 每 次 运 行 程 序 时 重 复 输 入 。 而 且 以 后 要 用 数据 时 能 将 它 们 从 磁 盘 文 件 中 读 出 。2.功 能 模 块 设 计 根 据 前 面 对 校 园 信 息 管 理 系 统 基 本 信 息 和 功能 的 需 求 分 析 ,程 序 中 应 该 至 少 定 义 两 个 类 : 一 个 是 学 生 类 student,另 一 个 是 教 师 类teacher 另 外 , 为 了 便 于 对 教 师 和 学 生 信 息 进 行 统 一处 理 以 提 高 效 率 , 还 可 以 将 学 校 的 所 有 人 员 抽象 为 一 个 Person类 , 将 student和 teacher类 作为 其 派 生 类 。 因 此 , 可 画 出 系 统 的 对 象 模 型 如下 : person类定 义 数 据 类 型 描 述name char数 组 学 生 姓 名sex char数 组 学 生 性 别address char数 组 学 生 家 庭 地 址birthday Date (自 定 义 结 构 ) 出 生 日 期type ptype (自 定 义 枚 举 类 型 ) student 或 teachershow 虚 成 员 函 数 输 出 对 象 信 息read 虚 成 员 函 数 读 入 对 象 信 息save 虚 成 员 函 数 将 对 象 存 入 文 件Load 虚 成 员 函 数 从 文 件 读 入 对 象 student类 :public person定 义 数 据 类 型 描 述sclass char数 组 学 生 所 在 班 级major char数 组 所 学 专 业course course数 组 所 学 课 程 数 组sregister Date (自 定 义 结 构 ) 入 学 日 期show 虚 成 员 函 数 输 出 对 象 信 息read 虚 成 员 函 数 读 入 对 象 信 息save 虚 成 员 函 数 将 对 象 存 入 文 件Load 虚 成 员 函 数 从 文 件 读 入 对 象 teacher类 :public person定 义 数 据 类 型 描 述courses course数 组 所 教 课 程tregister Date (自 定 义 结 构 ) 到 校 日 期show 虚 成 员 函 数 输 出 对 象 信 息read 虚 成 员 函 数 读 入 对 象 信 息save 虚 成 员 函 数 将 对 象 存 入 文 件Load 虚 成 员 函 数 从 文 件 读 入 对 象另 外 , 在 校 园 信 息 管 理 系 统 中 , 如 果 要 输 出 全 部 人 员 信息 , 必 须 对 每 个 人 员 调 用 show函 数 , 为 使 系 统 能 自 动确 认 当 前 对 象 是 student类 对 象 还 是 teacher类 对 象 , 应将 person类 的 show、 read save load 定 义 为 虚 函 数 。 表 9-4 用 到 的 命 令 所 对 应 的 函 数 及 功 能 描 述命 令 对 应 函 数 功 能 描 述input inputCMD 输 入 数 据output outputCMD 输 出 数 据save saveCMD 将 数 据 存 入 文 件load readCMD 将 数 据 从 文 件 读 入analyze analyzeCMD 分 析 数 据exit exitCMD 退 出 系 统help helpCMD 显 示 帮 助 信 息
展开阅读全文