版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1,类与对象(1),1 深入学习一:关于类的定义 2 深入学习二:关于初始化列表 3 案例:舍罕王的失算 4 深入学习三:关于临时对象 5 案例:约瑟夫问题,2,类的定义格式 class 类名 private: 私有数据成员或成员函数; protected: 保护数据成员或成员函数; public: 公有数据成员或成员函数; ; 各个成员函数的实现;,1 深入学习一:关于类的定义,分号不可省略,否则编译器报错,3,一般的复合语句 无需分号 例如:函数的定义、循环语句等,1 深入学习一:关于类的定义,int func() 语句; ,for(i=0;i3;i+) 语句; ,4,原因 类在C+中被当
2、做一种数据类型。 凡是直接跟在数据类型后面的标识符,不是变量就是函数。 因此,类的定义结束后,如果不在其后加分号,就会将其后面的内容解释成一个变量或函数,从而导致错误。,1 深入学习一:关于类的定义,5,一个简单的例子 #include using namespace std; int g; int main() coutgendl; ,1 深入学习一:关于类的定义,输出结果: 0,6,对程序的修改 将全局变量 g 的类型换成某一个类。,1 深入学习一:关于类的定义,#include using namespace std; class A int num; public: A()num=6;
3、 friend ostream ,输出结果: 6,7,说明: 直接出现在类定义后面的标识符,被编译器解释成该类类型的一个变量。 如果该标识符后跟括号,则该标识符代表函数。 这是“紧凑”写法,通常不用。 忘记类定义后的分号? 通常, 程序无法通过编译。,1 深入学习一:关于类的定义,#include using namespace std; class A int num; public: A()num=6; friend ostream ,8,说明: 由于在类定义后缺少分号,编译器会将紧跟在class A定义之后的int当做类型A的一个变量。 一个例子: #include using name
4、space std; int main() int; cout“Hello, World!”endl; ,1 深入学习一:关于类的定义,9,知识回顾 不能在类体中直接指定数据成员的初值。 要通过调用对象的构造函数进行初始化。 例子:,2 深入学习二:关于初始化列表,#include using namespace std; class A int i; public: A() i=1; void show() coutiendl; ; int main() A().show; ,#include using namespace std; class A int i; public: A() i
5、=1; void show() coutiendl; ; class B int i; public: B():i(1) void show() coutiendl; ; int main() A().show(); B().show(); ,10,说明 对于数据成员为int型的变量,其初始化的位置可以在构造函数的函数体内,也可以放在初始化列表中。 其他情况 如:数据成员是引用、常变量、类对象,2 深入学习二:关于初始化列表,#include using namespace std; class A int num; public: A(int i) num=i; void show() co
6、utnumendl; ; class B int ,int e=5; B:B(int i):r(e),PI(3.1415926),a(i) int main() B(1).show(); ,11,说明: B:B(int i) r=e; PI=3.1415926; a=A(i); 初始化与赋值的区别: 赋值操作是在两个已经存在的对象间进行的,而初始化是要创建一个新的对象,并且其初值来源于另一个已存在的对象。,2 深入学习二:关于初始化列表,12,用赋值代替初始化 不会发生编译错误,但程序运行效率降低。 例子:,2 深入学习二:关于初始化列表,#include using namespace st
7、d; class A int num; public: A() cout“In default constructor”endl; A(int i) cout“In user-defined constructor”endl; num=i; A ,B:B(int i)a=A(i); int main() B b(1); b.show(); ,输出结果: In default constructor In user-defined constructor Using assignment 1,13,结论 如果没有显示地在初始化列表中对成员对象a进行初始化,则在进入类B的构造函数体之前,会先调用类
8、A的默认构造函数。 在类B的构造函数体内进行的是赋值操作,并且要调用类A的构造函数A(int)先生成一个无名对象。 改造类B的构造函数: B:B(int i):a(i) 输出结果: In user-defined constructor 1,2 深入学习二:关于初始化列表,14,初始化列表中各部分的执行顺序 与书写顺序无关。 遵循的原则: 基类的构造函数最先执行 其他的成员按照它们在类中声明的顺序依次被初始化 数组成员的初始化 在初始化列表中,无法完成为对象的数组成员进行初始化的工作。 原因: C+语言没有提供这样的机制,只能在构造函数体内分别为成员数组的每个元素分别赋初值。,2 深入学习二:
9、关于初始化列表,15,数组成员的初始化 如果数组元素本身也是对象,这种赋值操作会造成较大的运行时开销。 此外,如果在类体中定义一个常量数组? class A const int arr3; public: A(); ; 定义构造函数 A:A():arr1,2,3 A:A():arr(1,2,3) A:A():arr0(1),arr1(2),arr2(3) ,2 深入学习二:关于初始化列表, ,16,结论: 不能在一个类中定义一个常量数组。 实际应用中,通常在类中定义静态的常量数组。 思考题 如果确实想在类中定义一个常量数组,怎么办?,2 深入学习二:关于初始化列表,17,2 深入学习二:关于初
10、始化列表,#include using namespace std; int *CreateArr(int n) int *p; p=new intn; for(int i=0;in;i+) pi=i+1; return p; class A int arrsize; const int *const arr; public: A(int n):arr(CreateArr(n) arrsize=n; void show() for(int i=0;iarrsize;i+) coutarri ; coutendl; A()delete arr; ;,int main() A a(3); a.sh
11、ow(); ,18,程序分析: 由于arr是一个指向常量的指针常量,所以arr的初始化工作一旦完成,就不能改变arr数组元素的值,也不能将arr指向别处。 客观上arr与一个常量数组的作用是相同的。,2 深入学习二:关于初始化列表,19,舍罕是古印度的国王,据说他十分好玩,宰相达依尔为讨好国王,发明了现今的国际象棋献给国王。舍罕非常喜欢这项游戏,于是决定嘉奖达依尔,许诺可以满足达依尔提出的任何要求。达依尔指着舍罕王前面的棋盘提出了要求:“陛下,请您按棋盘的格子赏赐我一点麦子吧,第1个小格赏我一粒麦子,第2个小格赏我两粒,第3个小格赏我四粒,以后每一小格都比前一个小格赏的麦粒数增加一倍,只要把棋
12、盘上全部64个小格按这样的方法得到的麦粒都赏赐给我,我就心满意足了。”舍罕王听了达依尔这个小小的要求,想都没想就满口答应下来。结果在给达依尔麦子时舍罕惊奇地发现它要给达依尔的麦子比自己想象的要多得多,于是他进行了计算,结果令他大惊失色。舍罕王的计算结果是多少粒麦子?,轻松一刻:舍罕王的失算,20,数学模型: 求2i-1的累加和(i从1到64),轻松一刻:舍罕王的失算,#include #include #include using namespace std; int main() double sum=0; int i; for(i=1;i=64;i+) sum+=pow(2.0,i-1);
13、 cout“The number of the grain is ”endl; coutsetprecision(20)sumendl; system(“pause”); ,21,什么是临时对象: 在程序中没有显式地给出创建对象的语句,但确实产生了的对象。 临时对象是在栈上产生的。 何时会临时对象出现? (1)接收函数的返回值 (2)用于实现隐式的类型转换 例子:,3 深入学习三:关于临时对象,#include using namespace std; class X static int order; char ch; int n; public: X(char c) order+; n=o
14、rder; ch=c; cout“Constructing object”nendl; X() cout“Destructing object”nendl; X(X,int X:order; X makewho() X B(B); return B; int main() X A(A); A=makewho(); ,22,结论: 函数返回的对象位于何处?怎样送到A中? 语句A=makewho();等同于两条语句的执行结果: X C(makewho(); A=C; 即: 在makewho()函数内部,产生了一个局部对象B,函数的返回值就是根据B的值决定的。 要把makewho()函数内部的对象B
15、的值传递到主调函数中的对象A中,实际上是在主调函数中生成一个临时对象,这个临时对象是由对象B作参数调用类X的复制构造函数产生的。然后,再将临时对象的值赋给对象A完成规定的操作。,3 深入学习三:关于临时对象,23,根据运行结果可知: 临时对象除了“不显式产生”之外,它的其他方面跟普通对象一样:产生的时候调用构造函数,消亡的时候调用析构函数,可以访问临时对象的成员,对临时对象进行寻址操作等。,3 深入学习三:关于临时对象,输出结果: Constructing object 1 Constructing object 2 Constructing object 3 by copying Destr
16、ucting object 2 Destructing object 3 Destructing object 1,24,问题 用于展示面向过程的程序设计和面向对象的程序设计在组织代码方面的差异。 约瑟夫问题: 设有n个人围坐在一个圆桌周围,现从第s个人开始报数,报到第m个人出列,然后从出列的下一个人重新开始报数,数到第m个人又出列,如此重复直到所有的人全部出列为止。写出n个人的出列顺序。 假设s=1。采用数组解决,将所有的人的序号存在数组中,然后开始循环遍历数组,每出列一个人,就将数组对应元素的值修改为0,直到所有人员都出列。,4 案例:约瑟夫问题,25,面向过程的程序设计,4 案例:约瑟夫
17、问题,#include #include int *JosephWithArray(int n) int *p; p=new intn; for(int i=0;in;i+) pi=i+1; return p; int NextPeople(int prev, int *WorkingArray, int number_of_people, int step) int count=0; int travel=prev; int emptyplace=0; while(countstep) travel=(travel+1) % number_of_people; if(WorkingArray
18、 travel) count+; emptyplace=0; else emptyplace+; if(emptyplace=number_of_people) return -1; return travel; ,26,面向过程的程序设计,4 案例:约瑟夫问题,void CreateOutput(int *WorkingArray, int number_of_people, int step) int i; int outnum=-1; for(i=0;i-1 ,27,面向对象的程序设计,4 案例:约瑟夫问题,#include #include using namespace std; c
19、lass Joseph protected: int number_of_people; int step; public: virtual void CreateOutput()=0; Joseph(int n, int m) number_of_people=n; step=m; ; class JosephWithArray:public Joseph int *WorkingArray; int NextPeople(int prev);public: JosephWithArray(int n, int m); void CreateOutput(); JosephWithArray() delete WorkingArray; ; JosephWithArray:JosephWithArray(int n, int m):Joseph(n.m) WorkingArray=new intn; for(int i=0;in;i+) WorkingArrayi=i+1; ,28,面向对象的程序设计,4 案例:约瑟夫问题,void JosephWithArray:CreateOutput() int i; int outnum=-1; for(i=0;i-1 ,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安全生产年终检测讲解
- 生物工程专业女生就业指南
- 德国机器人工程师就业前景
- 道路客运调度员岗前工作考核试卷含答案
- 主管护师职业发展规划路径
- 紫胶热滤工岗前技术知识考核试卷含答案
- 瓦斯泵工安全专项模拟考核试卷含答案
- 地震勘探工岗前实操操作考核试卷含答案
- 轧钢成品工岗位晋升测试考核试卷含答案
- 磁头制造工岗前实操能力考核试卷含答案
- 四川能投发展股份有限公司所属公司2026年员工公开招聘考试参考题库及答案详解
- 药品车间质量奖惩制度
- 沪教版(五四学制)2026年数学七年级下册期末测试卷(含答案解析)
- 三级安全教育切割作业测试试题附答案
- 老挝用工合同范本
- 检察院安全生产工作制度
- 2026云南昆明巫家坝建设发展有限责任公司校园招聘15人备考题库及答案详解(网校专用)
- 2026云南曲靖国金资本运营集团有限公司招聘3人笔试历年常考点试题专练附带答案详解
- 《小学数学教学设计》小学教育专业全套教学课件
- 2025-2026学年黑龙江省齐齐哈尔市建华区八年级(上)期末英语试卷(含答案)
- 冠心病诊疗指南(2025版)
评论
0/150
提交评论