Microsoft PowerPoint - 第06讲_继承.ppt [兼容模式]

Similar documents
幻灯片 1

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

Microsoft PowerPoint - 04-Inheritance.ppt

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

Microsoft PowerPoint - string_kruse [兼容模式]

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf ("%d", & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

无类继承.key

C++_Lecture

第七讲 继承与多态

Strings

Chapter12 Derived Classes

c_cpp

运算符重载 为什么要 运算符重载 那些运算符可以重载, 哪些不可以 如何实现运算符重载 实现方式 : 成员函数与非成员函数 类型转换 怎样实现对象与基本数据类型数据的运算 2

untitled

Microsoft PowerPoint - 第07讲_多态1.ppt [兼容模式]

C++ 程序设计 实验 2 - 参考答案 MASTER 2017 年 5 月 21 日 1

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式]

新版 明解C++入門編

幻灯片 1

<4D F736F F F696E74202D20B5DA3032BDB25FC0E0BACDB6D4CFF3312E BBCE6C8DDC4A3CABD5D>

FY.DOC

北京大学

第3章.doc

程序设计语言及基础

NOWOER.OM m/n m/=n m/n m%=n m%n m%=n m%n m/=n 4. enum string x1, x2, x3=10, x4, x5, x; 函数外部问 x 等于什么? 随机值 5. unsigned char *p1; unsigned long *p

C/C++语言 - C/C++数据

软件工程文档编制

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

Strings

面向对象的程序设计 : 抽象 继承和多态 Dongke Sun (Southeast University) C++ Programming and Algorithms April 12, / 38

Microsoft PowerPoint - 07 派生数据类型

Microsoft PowerPoint - 10 模板 Template.pptx

chap07.key

幻灯片 1

Microsoft PowerPoint - CPP-Ch Print.ppt [兼容模式]

Microsoft Word cppFinalSolution.doc

untitled

提纲 1 联编与多态性 2 用虚函数实现多态 3 虚函数的工作原理 4 纯虚函数与抽象类 5 总结与思考 Dongke Sun (Southeast University) C++ Programming and Algorithms April 12, / 36

Microsoft Word - ch04三校.doc

OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

提问袁小兵:

Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式]

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

ebook55-13

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

C 1

untitled

Modeling & Simulation 数学原理 物理规律和程序设计的综合 Magic Fluids Heart Simulator Dongke Sun (Southeast University) C++ Programming and Algorithms April 23,

Microsoft PowerPoint - L17_Inheritance_v4.pptx

Microsoft Word - 新1-12.doc

Microsoft Word - 物件導向編程精要.doc

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

Microsoft Word - 第3章.doc

内 容 提 要 指 针 持 久 动 态 内 存 分 配 字 符 串 ( 字 符 数 组 ) 2

untitled

Guava学习之Resources

ebook39-5

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

相 应 功 能 (5) 再 将 Boy 类 作 为 Girl 类 的 友 元 类, 在 Boy 类 的 某 成 员 函 数 VisitGirl(Girl & ) 中 访 问 Girl 类 的 私 有 成 员, 观 察 编 译 器 给 出 的 信 息 ( 6 ) 删 除 两 个 类 中 的 函 数 V

Microsoft Word - 第7章 类与对象.docx

内部明电

PowerPoint Presentation

《C语言程序设计》教材习题参考答案

運算子多載 Operator Overloading

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

幻灯片 1

Microsoft Word - 澎湖田調報告-宏達組9804.doc

平 凡 足 迹 李 本 川 作 者 为 中 国 科 学 院 海 洋 研 究 所 研 究 员,1935 年 生, 山 东 荣 成 人 我 今 年 63 岁 了 大 前 年 丈 夫 和 儿 子 在 一 个 月 内 先 后 离 开 了 人 世, 女 儿 又 已 出 嫁, 现 在 是 孑 然 一 身 我 是

今天 年春季号 总 92 期

*

( ) / / / / / / /

(Microsoft Word - 8\244T\244\362\277\337\272]\244W\265L\246W.doc)

Microsoft Word - 專家本色 doc


但, 你 应 该 听 过 我 们 走 在 大 路 上 这 首 歌, 或 许 还 知 道 革 命 人 永 远 是 年 轻 那 支 歌 ; 并 且, 几 乎 可 以 肯 定, 你 在 戴 红 领 巾 的 那 阵, 必 然 唱 过 牛 儿 还 在 山 坡 吃 草, 放 牛 的 却 不 知 道 哪 儿 去

2 临 终 助 念 答 问 序 临 终 关 怀, 由 佛 门 净 宗 古 来 祖 师 大 德 提 倡 助 念 往 生, 现 今 已 渐 为 社 会 大 众 所 重 视, 在 台 湾, 台 大 长 庚 等 各 大 医 院, 也 都 设 有 助 念 室 ; 大 陆 上 许 多 道 场, 也 有 专 为

校园之星

<4D F736F F F696E74202D FA8BEA861B8EAB7BDBEE3A658BB50C0B3A5CE28B773A6CBA5AB29>


之 原 則 及 國 防 部 訂 頒 國 軍 列 管 國 有 不 動 產 提 供 非 軍 方 單 位 使 用 處 理 原 則 規 定 不 符, 仍 應 以 出 租 方 式 辦 理 惟 可 就 偏 遠 地 區 提 供 官 兵 金 融 水 電 服 務 使 用 部 分, 研 議 降 低 租 金 標 準, 報

chineseall

釋禪波羅蜜次第法門

证券代码: 证券简称:锦江股份 公告编号:【】

1700 装 卸 搬 运 7645 装 卸 搬 运 服 务 2100 建 筑 7410 工 程 服 务 11% 装 卸 搬 运 服 务, 是 指 使 用 装 卸 搬 运 工 具 或 者 人 力 畜 力 将 货 物 在 运 输 工 具 之 间 装 卸 现 场 之 间 或 者 运 输 工 具 与 装 卸

前 言 教 育 无 小 事, 它 成 就 着 学 生 的 未 来 作 为 教 师, 他 们 无 时 无 刻 不 在 关 注 着 学 生 的 成 长 学 生 的 未 来 学 生 就 像 一 朵 含 苞 待 放 的 花 朵, 需 要 老 师 们 的 细 心 呵 护, 给 学 生 需 要 的 东 西, 而

《盗墓笔记》 南派三叔/著

<CFFBB7D1D5DFD0D0CEAAD1A72E6D7073>

独立学院建设与发展


模板

1.5招募说明书(草案)

NethersoleJO89(8).indd

2013 C 1 #include <stdio.h> 2 int main(void) 3 { 4 int cases, i; 5 long long a, b; 6 scanf("%d", &cases); 7 for (i = 0; i < cases; i++) 8 { 9 scanf("%

Transcription:

程序设计实习 (I): C++ 程序设计 第六讲继承

上节内容回顾 三种运算符重载的实现方式 重载为普通函数 重载为成员函数 重载为友元 常见的运算符重载 流运算符 (>> <<) 自增 / 自减运算符 (++ --) 赋值号 (=) 下标运算符 ([]) 类型转换运算符 2

[ 补充 ] 类型转换运算符重载 类型转换 Operator type(); 必须为成员函数, 不指定返回类型, 形参为空 一般不改变被转换对象, 因此常定义为 const 类型转换自动调用 3

主要内容 基本概念 : 继承 基类 派生类 派生类的成员组成 可见性 派生类的构造 析构 派生类与基类的指针类型转换 4

继承机制 : 从例子开始 姓名 姓名 学号 学号 学生 性别成绩 中学生 性别成绩 是否该奖励? 姓名 竞赛获奖是否该奖励? 姓名学号 学号 性别 大学生 性别成绩 研究生 成绩院系 院系 导师 是否该奖励? 是否该奖励? 5 是否保研? 是否发 RA?

继承 继承与派生的概念 在定义一个新的类 B 时, 如果该类与某个已有的类 A 相似 ( 指的是 B 拥有 A 的全部特点 ) A-- 基类 ( 父类 ),B-- 基类的派生类 ( 子类 ) 派生类是通过对基类进行修改和扩充得到的 在派生类中, 可以扩充新的成员变量和成员函数 派生类一经定义后, 可以独立使用, 不依赖于基类 派生类拥有基类的全部成员, 包括 private, protected, public 成员变量和 private, protected, public 方法 在派生类的各个成员函数中, 不能访问基类中的 private 成员 6

需要继承机制的例子 所有的学生都有一些共同属性和方法 属性 : 姓名, 学号, 性别, 成绩等 方法 : 判断是否该留级, 判断是否该奖励等 但不同的学生, 比如中学生, 大学生, 研究生, 又有各自 不同的属性和方法 e.g. 大学生有系的属性, 而中学生没有, 研究生有导师的属性, 中学生竞赛 特长加分之类的属性 如果为每类学生都编写一个类 不少重复的代码, 浪费 比较好的做法 : 编写一个 学生 类, 概括了各种学生的共同特点 从 学生 类派生出 大学生 类, 中学生 类, 研究生类 7

class CStudent { private: char szname[20]; int nage; int nsex; public: bool IsThreeGood() { int SetSex( int nsex_ ) { nsex = nsex_ ; } void SetName( char * szname_ ) { strcpy( szname, szname_); } //... // 派生类的写法是 : 类名 : public 基类名 class CUndergraduateStudent : public CStudent { private: int ndepartment; public: bool IsThreeGood() {... // 覆盖 bool CanBaoYan() {... // 派生类的写法是 : 类名 : public 基类名 8

class CGraduateStudent : public CStudent { private: int ndepartment; char szsupervisorname[20]; public: int CountSalary() {... 9

继承 : 是 关系 基类 A B 是基类 A 的派生类 复合与继承 逻辑上要求 : 一个 B 对象也是一个 A 对象 复合 : 有 关系 复合, 即一个类的对象拥有作为其成员的其它类的对象其象 d 是类 C 的成员 d 是类 D 的一个对象 复合关系满足 :C 类中 有 成员对象 d 10

继承的使用 写了一个 CMan 类代表男人 又发现需要一个 CWoman 类来代表女人 仅仅因为 CWoman 类和 CMan 类有共同之处, 就让 CWoman 类从 CMan 类派生而来, 是不合理的 因为 一个女人也是一个男人 从逻辑上不成立 好的做法是概括男人和女人共同特点, 写一个 CHuman 类, 代表 人, 然后 CMan 和 CWoman 都从 CHuman 派生 11

复合关系的使用 几何形体程序中, 需要写 点 类, 也需要写 圆 类, 两者的关系就是复合关系 每一个 圆 对象里都包含 ( 有 ) 一个 点 对象, 这个 点 对象就是圆心 12 class CPoint { double x, y; friend class CCircle; // 便于 CCirle 类操作其圆心 class CCircle { double r; CPoint center;

写一个小区养狗管理程序 复合关系的使用 需要写一个 业主 类, 还需要写一个 狗 类 而狗是有 主人 的, 主人当然是业主 ( 假定狗只有一个主人, 但一个业主可以有最多 10 条狗 ) 13

class CDog; class CMaster { CDog dogs[10]; class CDog { CMaster m; 这段程序有问题吗? 复合关系的使用 14

正确写法 : 复合关系的使用 为 狗 类设一个 业主 类的成员对象指针 为 业主 类设一个 狗 类的对象指针数组 class CDog; class CMaster { CDog * dogs[10]; class CDog { CMaster * m; 15

继承 派生类可以定义一个和基类成员同名的成员, 这叫 覆盖 在派生类中访问这类成员时, 缺省的情况是访问派 生类中定义的成员 要在派生类中访问由基类定义的同名成员时, 要使 用作用域符号 :: 16

基类和派生类有同名成员的情况 class base { class derived d: public base{ int j; public: public: int i; int i; void access(); void func(); void func(); void derived::access(){ Obj 占用的存储空间 j = 5; //error Base::j i = 5; // 引用的是派生类的 i base::i =5;// 引用的是基类的 i Base::i func(); // 派生类的 base::func(); // 基类的 i } 一般来说, 基类和派生类 derived obj; 不定义同名成员变量 obj.i = 1; obj.base::i = 1; 17

另一种存取权限说明符 :protected 基类的 private 成员 : 可以被下列函数访问 基类的成员函数 基类的友员函数 基类的 public 成员 : 可以被下列函数访问 基类的成员函数 基类的友员函数 派生类的成员函数 派生类的友员函数 其他的函数 基类的 protected 成员 : 可以被下列函数访问 18 基类的成员函数 基类的友员函数 派生类的成员函数可以访问当前对象的基类的保护成员

保护成员 class Father { private: int nprivate; // 私有成员 public: int npublic; // 公有成员 protected: int nprotected; // 保护成员 class Son : public Father{ void AccessFather () { npublic = 1; // ok; nprivate Pi = 1; // wrong nprotected = 1; // OK, 访问从基类继承的 protected 成员 Fth Father f; f.nprotected = 1; //wrong, f 不是函数所作用的当前对象 } 19

int main() { Father f; Son s; f.npublic = 1; // Ok s.npublic = 1; // Ok f.nprotected = 1; // error f.nprivate = 1; // error s.nprotected = 1; //error s.nprivate = 1; // error return 0; } 20

派生类的构造函数 class Bug { private : int nlegs; g; int ncolor; public: int ntype; Bug (int legs, int color); void PrintBug(){ class FlyBug: public Bug // FlyBug 是 Bug 的派生类 { int nwings; public: FlyBug(int legs, int color, int wings); 21

Bug::Bug(int legs, int color){ nlegs = legs; ncolor = color; } // 错误的 FlyBug 构造函数 FlyBug::FlyBug (int legs, int color, int wings){ nlegs = legs; // 不能访问 ncolor = color; // 不能访问表达式中可以出现 : ntype = 1; // ok FlyBug 构造函数 nwings = wings; 的参数 常量 } // 正确的 FlyBug 构造函数 FlyBug::FlyBug (int legs, int color, int wings):bug( legs, color){ nwings = wings; } 22

int main() { } FlyBug fb (2,3,4); fb.printbug(); fb.ntype = 1; fb.nlegs = 2 ; // error. nlegs is private return 0; 23

FlyBug fb (2,3,4); 在创建派生类的对象时, 需要调用基类的构造函数 : 初始化派生类对象中从基类继承的成员 在执行一个派生类的构造函数之前, 总是先执行基类的构造函数 调用基类构造函数的两种方式 显式方式 : 在派生类的构造函数中, 为基类的构造函数提供参数 derived::derived(arg_derived-list):base(arg_base-list) 隐式方式 : 在派生类的构造函数中, 省略基类构造函数时, 派生类的构造函数则自动调用基类的默认构造函数 派生类的析构函数被执行时, 执行完派生类的析构函数后, 自动调用基类的析构函数 24

class Base { public: int n; Base(int i):n(i) { cout << "Base " << n << " constructed" << endl; } ~Base() { cout << "Base " << n << " destructed" << endl;} class Derived:public Base { public: Derived(int i):base(i) { cout << "Derived constructed" t << endl; } ~Derived() { cout << "Derived destructed" << endl; } int main() { Derived Obj(3); return 0; } 25

输出结果 : Base 3 constructed Derived constructed Derived destructed Base 3 destructed 26

包含成员对象的派生类的构造函数 class Skill{ public: Skill(int n) { } class FlyBug: public Bug { int nwings; Skill sk1, sk2; public: FlyBug( int legs, int color, int wings); FlyBug::FlyBug( int legs, int color, int wings): Bug(legs, color), sk1(5), sk2(color) { nwings = wings; } 表达式中可以出现 :FlyBug 构造函数的参数 常量 27

在创建派生类的对象时, 在执行一个派生类的构造函数之前 : 调用基类的构造函数 : 初始化派生类对象中从基类继承的成员 调用成员对象类的构造函数 : 初始化派生类对象中成员对象 派生类的析构函数被执行时, 执行完派生类的析构函数后 : 调用成员对象类的析构函数 ; 调用基类的析构函数 析构函数的调用顺序与构造函数的调用顺序相反 28

public 继承的赋值兼容规则 class base { class derived : public base { base b; derived d; base derived 派生类的对象可以赋值给基类对象 b = d; 派生类对象可以初始化基类引用 base & br = d; 派生类对象的地址可以赋值给基类指针 base * pb = & d; 29

基类与派生类的指针强制转换 派生类对象的指针可以直接赋值给基类指针 Base * ptrbase = &objderived; ptrbase tb 指向的是一个 Derived 类的对象 *ptrbase 可以看作一个 Base 类的对象, 访问它的 public 成员 直接通过 ptrbase, tb 不能够访问 objderived 由 Derived 类扩 展的成员 通过强制指针类型转换, 可以把 ptrbase 转换成 Derived 类的指针 Base * ptrbase = &objderived; Derived *ptrderived = (Derived * ) ptrbase; 程序员要保证 ptrbase 指向的是一个 Derived 类的对象, 否则 很容易会出错 30

#include <iostream> using namespace std; class Base { protected: int n; public: Base(int i):n(i){ cout << "Base " << n << " constructed" << endl; } ~Base() { cout << "Base " << n << " destructed" << endl; } void Print() { cout << "Base:n=" << n << endl;} 31

class Derived:public Base { public: int v; Derived(int i):base(i),v(2 * i) { cout << "Derived constructed" << endl; } ~Derived() { cout << "Derived destructed" << endl; } void Func() { } ; void Print() { } cout << "Derived:v=" << v << endl; cout << "Derived:n=" << n << endl; 32

int main() { Base objbase(5); Derived objderived(3); Base * pbase = & objderived ; //pbase->func(); //err; Base 类没有 Func() 成员函数 //pbase->v = 5; //err; Base 类没有 v 成员变量 pbase->print(); //Derived * pderived = & objbase; //error Derived * pderived = (Derived *)(& objbase); pderived->print(); // 慎用, 可能出现不可预期的错误 pderived->v v = 128; // 往别人的空间里写入数据, 会有问题 objderived.print(); return 0; } 33

Derived * pderived = (Derived *)(& objbase); pderived n v }objbase n v } objderived 34

输出结果 : Base 5 constructed Base 3 constructed Derived constructed Base:n=3 Derived:v=0 Derived:n=5 Derived:v=6 Derived:n=3 Derived destructed Base 3 destructed Base 5 destructed 35

直接基类与间接基类 类 A 派生类 B, 类 B 可再派生类 C, 类 C 派生类 D, 类 A 是类 B 的直接基类 类 B 是类 C 的直接基类, 类 A 是类 C 的间接基类 类 C 是类 D 的直接基类, 类 A B 是类 D 的间接基类 在声明派生类时, 派生类的首部只需要列出它的直接基类 派生类的首部不要列出它的间接基类 派生类沿着类的层次自动向上继承它的间接基类 派生类的成员包括 派生类自己定义的成员 直接基类中定义的成员 间接基类的全部成员 36

#include <iostream> using namespace std; class Base { public: int n; Base(int ti) i):n(i) { cout << "Base " << n << " constructed" << endl; } ~Base() { cout << "Base " << n << " destructed" << endl; } 37

class Derived:public Base { public: Derived(int i):base(i) { cout << "Derived constructed" << endl; } ~Derived() { cout << "Derived destructed" << endl; } 38

class MoreDerived:public Derived { public: MoreDerived():Derived(4) { cout << "More Derived constructed" <<endl; } ~MoreDerived() { cout << "More Derived destructed" << endl; } int main() { MoreDerived Obj; return 0; } 39

输出结果 : Base 4 constructed Derived constructed More Derived constructed More Derived destructed Derived destructed Base 4 destructed 40

总结 基本概念 : 继承 基类 派生类 合理派生 派生类的成员组成 可见性 private/protected 成员的继承性 在派生类的各个成员函数中, 不能访问基类中的 private 成员 派生类的构造 析构 构造顺序 : 基类 对象成员 派生 析构反之 派生类与基类的指针类型转换 f( 派生类 ) y( 基类对象 ):f: 对象 / 对象地址 ;y: 对象 / 引用 / 指针 基类指针 ( 强制指针类型转换 ) 派生类指针 41

42