<4D F736F F F696E74202D20B5DA3032BDB25FC0E0BACDB6D4CFF3312E BBCE6C8DDC4A3CABD5D>

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

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

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

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

幻灯片 1

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

c_cpp

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

Microsoft Word - 新1-12.doc

幻灯片 1

Microsoft PowerPoint - 10 模板 Template.pptx

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

Guava学习之Resources

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

无类继承.key

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

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

Microsoft PowerPoint - string_kruse [兼容模式]

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

chap07.key

untitled

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

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

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

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式]

程序设计语言及基础

新版 明解C++入門編

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

Chapter12 Derived Classes

第3章.doc

第七讲 继承与多态

untitled

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

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

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

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

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

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

FY.DOC

Strings

<4D F736F F F696E74202D20B5DA3031BDB25F432B2BB3CCD0F2C9E8BCC6B8C5CAF62E BBCE6C8DDC4A3CABD5D>

模板

Microsoft PowerPoint - 04-Inheritance.ppt

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


酒 神 (长篇小说)

北京大学

(Microsoft Word - 136\260g\270\364\252\272\267s\256Q.doc)

提问袁小兵:

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

untitled

软件工程文档编制

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

untitled

幻灯片 1

《培养一个真正的人》( )

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

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3

Strings

<4D F736F F F696E74202D20332D322E432B2BC3E6CFF2B6D4CFF3B3CCD0F2C9E8BCC6A1AAD6D8D4D8A1A2BCCCB3D0A1A2B6E0CCACBACDBEDBBACF2E707074>

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

程序设计与算法语言 拷贝构造 C/C++ Programming and Algorithms Copy Constructor Dongke Sun ( 孙东科 ) 东南大学机械工程学院 School of Mechanical Engineering South

untitled

Microsoft PowerPoint - L17_Inheritance_v4.pptx

Microsoft Word cppFinalSolution.doc

Microsoft Word - 01.DOC

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

Microsoft Word - word模板-教师.doc

保母人員丙級應檢資料第二部份 doc

4. if 与 else 在使用过程中为避免嵌套出现二义性,C++ 中规定与 else 子句配对的是 ( ) A. 其之前最近的 if 语句 B. 其之前最近且尚未配对的 if 语句 C. 缩排位置相同的 if 语句 D. 其之后最近的 if 语句答案 :B 解析 :C++ 中规定与 else 子句

教案模板4-2

Microsoft PowerPoint - C语言课件-9-结构体.pptx

C++ 程序设计 OJ9 - 参考答案 MASTER 2019 年 6 月 7 日 1


《计算概论》课程 第十九讲 C 程序设计语言应用

untitled

(6) 要 求 付 款 管 理 员 从 预 订 表 中 查 询 距 预 订 的 会 议 时 间 两 周 内 的 预 定, 根 据 客 户 记 录 给 满 足 条 件 的 客 户 发 送 支 付 余 款 要 求 (7) 支 付 余 款 管 理 员 收 到 客 户 余 款 支 付 的 通 知 后, 检

untitled

Microsoft Word - ch04三校.doc

Book1

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

工 序 的 是 ( ) A. 卷 筒 切 筒 装 药 造 粒 B. 搬 运 造 粒 切 引 装 药 C. 造 粒 切 引 包 装 检 验 D. 切 引 包 装 检 验 运 输 7. 甲 公 司 将 其 实 施 工 项 目 发 包 给 乙 公 司, 乙 公 司 将 其 中 部 分 业 务 分 包 给

C++ 程式設計

Microsoft Word - chap10.doc

PowerPoint 演示文稿

OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac)

<4D F736F F D20A1BE A1BF C4EABDADCBD5D7CFBDF0C5A9B4E5C9CCD2B5D2F8D0D0B9C9B7DDD3D0CFDEB9ABCBBEB8FAD7D9C6C0BCB6B1A8B8E6A3A8B8FAD7D A3A9>

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

2015年计算机二级(C语言)模拟试题及答案(三)

Microsoft PowerPoint - 07 派生数据类型

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

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

网C试题(08上).doc

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

幻灯片 1

C 1

ASP.NET实现下拉框二级联动组件

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

今天 年春季号 总 92 期

*

Transcription:

程序设计实习 (I): C++ 程序设计 第二讲类和对象 (1)

面向对象的程序设计 面向对象的程序设计方法, 能够较好解决结构化程序设计中出现的问题 面向对象的程序 = 类 + 类 + + 类 设计程序的过程, 就是设计类的过程 2

面向对象的程序设计 面向对象的程序设计方法 : 将某类客观事物共同特点 ( 属性 ) 归纳出来, 形成一个数据结 构 ( 可以用多个变量描述事物的属性 ); 将这类事物所能进行的行为也归纳出来, 形成一个个函数, 这些函数可以用来操作数据结构 这一步称为 抽象 通过某种语法形式, 将数据结构和操作该数据结构的构的 函数 打包 在一起, 形成一个 类 使得数据结构和操作该数据结构的算法呈现出显而易 见的紧密关系, 这就是 封装 3

从客观事物抽象出类的例子 写一个程序, 输入矩形的长和宽, 输出面积和周长 比如对于 矩形 这种对象, 要用一个类来表示, 该如 何做 抽象 呢? 矩形的属性就是长和宽 因此需要两个变量, 分别代表长和宽 可以对矩形进行哪些操作 矩形可以有设置长和宽, 计算面积和计算周长这三种 行为 这三种行为, 可以各用一个函数来实现, 都需要用到 长和宽这两个变量 4

从客观事物抽象出类的例子 将长, 宽变量和设置长, 宽, 求面积, 以及求周长的三个 函数 封装 在一起, 就能形成一个 矩形类 长 宽变量成为该 矩形类 的 成员变量 三个函数成为该类的 成员函数 成员变量和成员函数统称为类的成员 类 带函数的结构 5

从客观事物抽象出类的例子 class CRectangle { public: int w, h; int Area() { return w * h; int Perimeter(){ return 2 * ( w + h ); void Init( int w_, int h_ ) { w = w_; h = h_; ; // 必须有分号 6

从客观事物抽象出类的例子 int main( ) { int w, h; CRectangle r; //r 是 CRectangle 类的一个对象 cin >> w >> h; r.init(w, h); cout << r.area() << endl << r. Perimeter(); return 0; 通过类, 可以定义变量 类定义出来的变量, 也称为类的实例, 就是我们所说的 对象 C++ 中, 类的名字就是用户自定义的类型的名字 可以象使用的类型的名字基本类型那样来使用它 CRectangle 就是一种用户自定义的类型 7

对象的内存分配 和结构体变量一样, 对象所占用的内存空间的大 小, 等于所有成员变量的大小之和 每个对象各有自己的存储空间 一个对象的某个 成员变量被改变了, 不会影响到另一个对象 8

如何使用类的成员变量和成员函数 用法 1: 对象名. 成员名 CRectangle r1, r2; r1.w = 5; r2.init(5,4); Init 函数作用在 r2 上, 即 Init 函数执行期间访问的 w 和 h 是属于 r2 这个对象的, 执行 r2.init 不会影响到 r1 用法 2: 指针 -> 成员名 CRectangle r1, r2; CRectangle * p1 = & r1; CRectangle * p2 = & r2; p1->w = 5; p2->init(5,4); //Init 作用在 p2 指向的对象上 9

如何使用类的成员变量和成员函数 用法 3: 引用名. 成员名 CRectangle r2; CRectangle & rr = r2; rr.w = 5; rr.init(5,4); //rr 的值变了,r2 的值也变 void PrintRectangle(CRectangle & r) { cout << r.area() << ","<< r.perimeter(); CRectangle r3; r3.init(5,4); PrintRectangle(r3); 10

引用的概念 类型名 & 引用名 = 某变量名 ; 此种写法就定义了一个引用, 并将其初始化为引用某个 变量 某个变量的引用, 和这个变量是一回事, 相当于该变量 的一个别名 int n = 4; int & r = n; r = 4; cout << r; // 输出 4 cout << n; // 输出 4 n = 5; cout << r; // 输出 5 定义引用时一定要将其初始化成引用某个变量, 不初始化编译不过 引用只能引用变量, 不能引用常量和表达式 11

引用的作用 C 语言中, 要写交换两个整型变量值的函数, 只能通 过指针 void swap( int * a, int * b) { int tmp; tmp=*a;*a=*b;*b=tmp; * a = * * b = tmp; int n1, n2; swap(& n1,& n2) ; // n1, n2 的值被交换 12

使用引用 : 引用的作用 void swap( int & a, int & b) { int tmp; tmp = a; a = b; b = tmp; int n1, n2; swap(n1, n2) ; // n1, n2 的值被交换 13

引用作为函数的返回值 函数的返回值可以是引用, 如 : #include <iostream> using namespace std; int n = 4; int & SetValue() { return n; int main() { SetValue() = 40; cout << n; return 0; 程序输出结果是 40 14

类的成员函数的另一种写法 成员函数体和类的定义分开写 class CRectangle { public: int w, h; int ta Area(); // 成员函数仅在此处声明 int Perimeter() ; void Init( int w_, int h_ ); ; 15

类的成员函数的另一种写法 int CRectangle::Area() { return w * h; int CRectangle::Perimeter() { return 2*( w + h); void CRectangle::Init( (int w_,int h_ ) { w = w_; h = h_; CRectangle:: 说明后面的函数是 CRectangle 类的成员函数, 而非普通函数 一定要通过对象或对象的指针或对象的引用才能调用 16

对象成员的访问权限 在类的定义中, 用下列权限关键字来说明对象成员 的访问权限 : private: 私有成员, 只能在成员函数内访问 public : 公有成员, 可以在任何地方访问 protected: 保护成员 ( 以后再说 ) 以上三种关键字出现的次数和先后次序都没有限制 17

对象成员的访问权限 定义一个类 class classname { ; private: 私有属性和函数 public: 公有属性和函数 protected: 保护属性和函数 说明类成员的可见性 18

对象成员的访问权限 如过某个成员前面没有上述关键字, 则缺省地被认 为是私有成员 class Man { it int nage; // 私有成员 char szname[20]; // 私有成员 public: void SetName(char * szname){ strcpy( Man::szName, szname); ; 19

对象成员的访问权限 在类的成员函数内部, 能够访问 : 当前对象的全部属性 函数 ; 同类其它对象的全部属性 函数 在类的成员函数以外的地方, 只能够访问 该类对象的公有成员 20

class CMan { private: char szname[30]; // 名字 public : float height, weight; // 保存一个人的身高和体重信息 void setname( char * name); void Func1( CMan man); ~CMan(); // 析构函数 ; void CMan :: setname( char * name) { CMan man; strcpy( man.szname, "Lily"); //ok, 此种访问方式可行 strcpy( szname, name); //ok void CMan::Func1(CMan man) { cout << man.szname; //ok CMan:: ~CMan() { 21

int main() { CMan man1, man2; strcpy(man1.szname, Tom1234567889 ); // 错, 不能访 // 问私有成员 man1.setname( "Tom12345678909887"); // ok man1.height 1h ht= 5; //ok return 0; 设置私有成员的目的是强制对成员变量的访问一定要通过成员函 数进行 以后成员变量的类型等属性修改后, 只需要更改成员函数即可 否则, 所有直接访问成员变量的语句都需要修改 设置私有成员的机制, 叫 隐藏 22

如果将上面的程序 内存空间紧张的手持设备上 将 szname 改为 char szname[5], 若 szname 不是私有, 那么就要 找出所有类似 strcpy(man1.szname, Tom1234567889 ); 这样的语句进行修改, 以防止数组越界 太麻烦! 如果将 szname 变为私有, 那么程序中就不会出现 ( 除非在类 的内部 ) strcpy(man1.szname, Tom1234567889 ); 所有对 szname 的访问都是通过成员函数来进行, 例如 : man1.setname( Tom12345678909887 ); 那么, 就算 szname 改短了, 上面的语句也不需要找出来修改, 只要改 setname 成员函数, 在里面确保不越界即可 23

函数重载 一个或多个函数, 名字相同而参数个数或参数类型 互不相同, 这叫做函数的重载 例如 : int Max(double f1, double f2) { int Max(int n1, int n2) { int Max(int n1, int n2, int n3) { 函数重载使得函数命名变得简单 24

函数的缺省参数 C++ 中, 写函数的时候可以让参数有缺省值, 那么 调用函数的时候, 若不写参数, 参数就是缺省值 void func( int x1 = 2, int x2 = 3) { func( ) ; // 等效于 func(2, 3) func(8) ; // 等效于 func(8, 3) func(, 8) ; // 不行 函数参数可缺省的目的在于提高程序的可扩充性 即如果某个写好的函数要添加新的参数, 而原先那些调用该 函数的语句, 未必需要使用新增的参数, 那么为了避免对原 先那些函数调用语句的修改, 就可以使用缺省参数 25

void func( int x1 = 2, int x2 = 3){ cout<<x1+x2<<endl; void testfunc(){ int a=1; int b=1; func(a, b); void func( int x1 = 2, int x2 = 3, int x3 = 3){ cout<<x1+x2<<endl; int k=x3; 26

成员函数的重载及参数缺省 成员函数也可以重载 ( 普通函数也可以 ) 成员函数和构造函数可以带缺省参数 ( 普通函数也可以 ) 27 #include <iostream> using namespace std; class Location { private : int x, y; public: void init( int x=0, int y = 0 ); void valuex( int val ) { x = val ; int valuex() { return x; ; void Location::init( int X, int Y) { x = X; y = Y;

int main() { Location A, B; A.init(5); A.valueX(5); cout << A.valueX(); return 0; 28

使用缺省参数要注意避免有函数重载时的二义性 class Location { private : int x, y; public: void init( int x =0, int y = 0 ); void valuex( int val = 0 ) { x = val; int valuex() { return x; ; Location A; A.valueX(); // 错误, 编译器无法判断调用哪个 valuex 29

成员函数的一种 构造函数 (Constructor) 名字与类名相同, 可以有参数, 不能有返回值 (void 也不行 ) 作用是对对象进行初始化, 如给成员变量赋初值 如果定义类时没写构造函数, 则编译器生成一个 缺省的无参数的构造函数 缺省构造函数无参数, 不做任何操作 30

如果定义了构造函数, 则编译器不生成缺省的无 参数的构造函数 对象生成时构造函数自动被调用 对象一旦生成, 就再也不能在其上执行构造函数 为类编写构造函数是好的习惯, 能够保证对象生 成的时候总是有合理的值 一个类可以有多个构造函数 31

class Complex { private : double real, imag; public: void Set( double r, double i); ; // 缺省构造函数 Complex c1; // 构造函数被调用 Complex * pc = new Complex; // 构造函数被调用 32

class Complex { private : double real, imag; public: Complex( double r, double i = 0); ; Complex::Complex( double r, double i){ real = r; imag = i; Complex c1; // error, 没有参数 Complex * pc = new Complex; // error, 没有参数 Complex c1(2); // OK Complex c1(2,4), c2(3,5); Complex * pc = new Complex(3,4); 33

可以有多个构造函数, 参数个数或类型不同 class Complex { private : double real, imag; public: void Set( double r, double i ); Complex(double r, double i ); Complex (double r ); Complex (Complex c1, Complex c2); ; Complex::Complex(double r, double i) { real = r; imag = i; 34

Complex::Complex(double r) { real = r; imag = 0; Complex::Complex (Complex c1, Complex c2); { real = c1.real+c2.real; real; imag = c1.imag+c2.imag; Complex c1(3), c2 (1,0), c3(c1,c2); // c1 = {3, 0, c2 = {1, 0, c3 = {4, 0; 35

构造函数最好是 public 的,private 构造函数不能直接用来初始化对象 class CSample{ private: CSample() { ; main(){ CSample Obj; //err. 唯一构造函数是 private 36

构造函数在数组中的使用 class CSample { int x; public: CSample() (){ cout << "Constructor 1 Called" << endl; CSample(int n) { x = n; cout << "Constructor 2 Called" << endl; ; 37

void main(){ CSample array1[2]; cout << "step1"<<endl; CSample array2[2] = {4,5; cout << "step2"<<endl; CSample array3[2] = {3; cout << "step3"<<endl; CSample * array4 = new CSample[2]; // 没有 delete, 不好 38

构造函数在数组中的使用 class Test { public: Test( int n) { //(1) Test( int n, int m) { //(2) Test() { //(3) ; Test array1[3] = { 1, Test(1,2) ; // 三个元素分别用 (1),(2),(3) 初始化 Test array2[3] = { Test(2,3), Test(1,2), 1; // 三个元素分别用 (2),(2),(1) 初始化 Test * parray[3] = { new Test(4), new Test(1,2) ; // 两个元素分别用 (1),(2) 初始化 40

复制构造函数 ( 拷贝构造函数 ) 形如 X::X( X& ), 只有一个参数即对同类对象的引用 如果没有定义构造函数, 那么编译器生成缺省复制构造函数 缺省的复制构造函数完成复制功能 class Complex { private : double real, imag; ; Complex c1; // 调用缺省构造函数 Complex c2(c1); // 调用缺省的复制构造函数 // 将 c2 初始化成和 c1 一样 41

如果定义的自己的复制构造函数, 则缺省的复制构造函数不存在 class Complex { public : double real,imag; Complex(){ Complex( Complex & c ) { real = c.real; imag = c.imag; cout << Copy Constructor called ; ; Complex c1; Complex c2(c1); // 调用自己定义的复制构造函数, // 输出 Copy Constructor called 42

不允许有形如 X::X( X ) 的构造函数 class CSample { ; CSample( CSample c ) { // 错, 不允许这样的构造函数 43

即使缺省的不带参数的构造函数不存在, 缺省的复 制构造函数仍然存在 class C1{ public: C1() { ; C1 c1, c2(c1); 44

复制构造函数在以下三种情况被调用 : a. 当用一个对象去初始化同类的另一个对象时 Complex c2(c1); Complex c2 = c1; b. 如果某函数有一个参数是类 A 的对象, 那么该函数被调用时, 类 A 的复制构造函数将被调用 void f( A a ) { a.x = 1; ; A aobj; f(aobj) ; // 导致 A 的复制构造函数被调用, 生成形 // 参传入函数 45

c. 如果函数的返回值是类 A 的对象时, 则函数返回时, A 的复制构造函数被调用 : A f( ) { A a; return a; // 此时 A 的复制构造函数被调用, // 即调用 A(a); intmain(){ A b; b = f(); return 0; 46

注意 : 对象间用等号赋值并不导致复制构造函数被调用 class CMyclass { public: int n; CMyclass() {; CMyclass( CMyclass & c) { n = 2 * c.n ; ; int main() { CMyclass c1,c2; c1.n = 5; c2 = c1; CMyclass c3(c1); cout <<"c2.n= n=" << c2.n << "";, cout <<"c3.n=" << c3.n << endl; return 0; 输出 : c2.n=5, c3.n=10 47

void fun(cmyclass obj_ ) { cout << "fun" << endl; 常量引用参数的使用 这样的函数, 调用时生成形参会引发复制构造函数调用, 开销比较大 所以可以考虑使用 CMyclass & 引用类型作为参数 如果希望确保实参的值在函数中不应被改变, 那么可以加上 const 关键字 : void fun(const CMyclass & obj) { // 函数中任何试图改变 obj 值的语句都将是变成非法 48

作业 实现一个学生信息处理程序 输入数据为一行 : 姓名, 年龄, 学号 ( 整数 ), 第一学年平均成绩, 第二学年平均成绩, 第三学年平均成绩, 第四学年平均成绩输出 : 姓名, 年龄, 学号, 四年平均成绩例如 : 输入 : Tom Hanks, 18, 7817, 80, 80, 90,70 输出 : Tom Hanks, 18, 7817, 80 要求实现一个代表学生的类, 并且所有成员变量都应该是私有的 49