版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2020/9/10,1,第1章 类和对象,应该重点掌握以下内容: 面向对象程序设计的基本特点 类和对象的定义和使用 构造函数和析构函数 拷贝构造函数和堆对象、对象数组 友元函数和友元类,2020/9/10,2,第1章 类和对象,1.1 面向对象程序设计概述 1.2 面向对象方法的基本特征 1.3 类和对象的定义 1.4 类的成员函数 1.5 对象成员的引用 1.6 构造函数和析构函数 1.7 类和对象的进一步应用 1.8 this指针 1.9 静态成员 1.10 友元函数和友元类 1.11 综合应用实例,2020/9/10,3,1.1 面向对象程序设计概述,一、什么是面向对象程序设计 面向对象
2、程序设计(Object Oriented Programming-简称OOP)是软件系统设计与实现的新方法,这种新方法即吸取了结构化程序设计的全部优点,又考虑了现实世界与面向对象空间的映射关系,所追求的目标是将现实世界的问题求解尽可能的简单化。 二、面向对象程序设计的基本思路,2020/9/10,4,1.2 面向对象方法的基本特征,1.2.1 对象和类 1.2.2 封装(encapsulation)与数据隐藏 1.2.3 继承(inheritance)与重用 1.2.4 多态性(polymorphism) 1.2.5 消息 1.2.6 面向过程与面向对象程序设计方法的比较,2020/9/10,
3、5,1.2.1 对象和类,一、现实世界与面向对象系统对应关系,2020/9/10,6,1.2.1 对象和类,二、什么是类 1. 类是一种复杂的数据类型,它将不同类型的数据和与这些数据相关的操作封装在一起。类是对现实世界客观事物的抽象。 2. 两方面的要素: 属性(atrribute)-数据 行为(behavior) -数据的操作 (函数) 三、什么是对象 对象是类的一个实体,又称为实例,2020/9/10,7,1.2.1 对象和类,四、对象与类的关系,人类 姓名 年龄 身高 体重 走路 学习 说话 开车 ,数据抽象,小王,小李,小张,人类的对象,2020/9/10,8,1.2.1 对象和类,五
4、、对象与对象之间消息传递,2020/9/10,9,1.2.2 封装与数据隐藏,一、什么是封装 封装是指将对象的数据和与这个数据有关的操作放在一起。 各个对象之间相互独立,互不干扰。 对象只留少量的接口,以便与外部联系。从外部看对象就像一个“黑匣子”,数据和方法是隐蔽的、看不见的。 当用户使用对象时,不必知道对象的具体实现细节,只需要根据对象提供的外部接口访问对象即可。,2020/9/10,10,1.2.2 封装与数据隐藏,二、封装应具有以下几个特点 具有一个清楚的边界,私有成员封装在内部,外部不可以访问 提供必要的接口 对象内部的数据和方法是受封装外壳保护的,其它对象不能直接使用。,主机 主板
5、 显卡 声卡 内存 数据传输线 电源线 ,USB接口,串行接口,电源开关,内 部 私 有 成 员,与 外 部 接 口,2020/9/10,11,1.2.3 继承与重用,一、继承概念的提出 例如:已定义电视机类,现需要定义彩色电视机类 解决方法: 1.重新设计 2.继承:继承原来电视机的属性和方法,再添加彩色电视机自己特有的新的属性和行为,2020/9/10,12,1.2.3 继承与重用,二、继承的概念 C+提供的继承机制提供了类之间相互关系的解决方案,使某个类可以继承另外一个类的特征和能力。 使用继承符合人们对事物的认识和叙述,大大简化了对问题的描述,提高了程序的可重用性,从而提高了程序设计、
6、修改、扩充的效率,实现软件重用(software reusability)。,2020/9/10,13,1.2.4 多态性(polymorphism),一、多态性的概念 多态性:描述的是同一个消息可以根据发送消息对象的不同采用不同的行为方式。 例如: 学校的上课铃响,不同班级的学生进入不同的教室学习,不同的老师进入不同教室开始讲课,不同的对象会作出不同的响应。可以看到学生和教师在接受到同一消息(上课铃声)时,执行不同的操作,这就是多态的表现。,2020/9/10,14,1.2.4 多态性(polymorphism),二、C+支持多态 静态多态性 动态多态性,2020/9/10,15,1.2.5
7、 消息,面向对象技术的封装使得对象相互独立,各个对象要相互协作实现系统的功能则需要对象之间的消息传递机制。消息是一个对象向另一个对象发出的服务请求,进行对象之间的通信。也可以说是一个对象调用另一个对象的方法(Method)或称为函数(Function)。,2020/9/10,16,1.2.6 面向过程与面向对象程序设计方法的比较,一、面向过程程序设计方法 程序 = 数据结构+算法 二、面向对象程序设计方法的规律是: 对象 = (数据结构+ 算法) 程序 = 对象 + 对象 + 对象 + + 对象,2020/9/10,17,1.3.1 类的定义,一、类定义组成 数据成员:说明类的属性 成员函数(
8、又称函数成员):对类数据成员操作的类内函数,又称为方法。 二、类定义的一般格式为 class 类名 public : 数据成员和成员函数实现 protected: 数据成员和成员函数实现 private: 数据成员和成员函数实现 ;,2020/9/10,18,1.3.1 类的定义,说明: (1)定义一个类时,使用关键字class;类名必须是一个合法的变量名; (2)一个类包括类头和类体两部分。 (3)大括号中定义的是类的数据成员和成员函数,称为类体(class body)。类定义结束要用“;”结束; (4)关键字public、 protected和private称为成员访问限定符。用访问限定符
9、声明了各个数据成员和成员函数的访问权限,2020/9/10,19,1.3.1 类的定义,三、访问限定符 公有(public):提供了与外界的接口功能。公有成员可以被本类中的成员使用和访问,还可以被类作用域内的其他外在其他函数使用。 私有(private):封装在类内部的,只能被该类的成员和该类友元函数或友元类访问,任何类以外的函数对私有成员的访问都是非法的。 保护(protected:访问权限介于私有和公有中间,类的成员可以访问,类以外的其他函数不能访问保护成员。,2020/9/10,20,1.3.1 类的定义,2020/9/10,21,1.3.1 类的定义,例:定义一个日期类Cdate,20
10、20/9/10,22,#include class Cdate /使用关键字class声明一个类,类名为Cdate public: /以下是公有成员函数 void Setdate (int y, int m,int d)/设置日期 year=y; month=m; day=d; /以上3行是函数的实现,2020/9/10,23,int Isleapyear()/判断日期是不是闰年 return (year%4=0,2020/9/10,24,1.3.2 类对象的定义,1先声明类类型,然后定义类对象 class 类名 对象列表 说明: (1)class 可选,可以写,也可以省略 (2)类名是定义好
11、的类。 (3)对象列表的格式为:对象名,对象名,对象名。定义多个对象时,各对象名中间用逗号隔开。 class Cdate date1,date2,date3; /Cdate是已经声明的类类型 Cdate date1,date2,date3; /建议使用的方法。,2020/9/10,25,2在声明类类型的同时定义对象 class 类名 数据成员和成员函数实现 对象列表; 3不写类名,直接定义类对象 class 数据成员和成员函数实现 对象列表;,1.3.2 类对象的定义,2020/9/10,26,1.3.3 类对象的内存分配,C+中用同一内存空间来存放这个同种类对象的成员函数代码,当去调用某个对
12、象的成员函数时,都去调用这个公用的函数代码。C+中用this指针来区分是哪个对象的成员函数。,2020/9/10,27,1.4 类的成员函数,类的成员函数也是函数的一种,它的与以前介绍的普通函数用法基本一样。 成员函数由函数头和函数体组成,函数头包括函数名、函数的参数及函数的类型。函数体主要说明函数实现的功能。,2020/9/10,28,1.4 类的成员函数,成员函数与一般函数的区别在于:它属于类的成员,出现在类体中,是类的一部分。使用类的成员函数时,要考虑类成员函数的访问权限。 类的成员函数可以在类体中定义,也可以在类体中声明类成员函数,成员函数的实现在类外定义。,2020/9/10,29,
13、1.4.1 在类内定义成员函数,#include class Cdate public: void Setdate (int y, int m,int d) /在类内定义成员函数 year=y; month=m; day=d; ,2020/9/10,30,1.4.1 在类内定义成员函数,int Isleapyear() return (year%4=0,2020/9/10,31,1.4.2 在类外定义成员函数,说明: 在类内定义的成员函数默认的是内联函数(inline函数)。一般把规模比较小的成员函数在类内定义。 通常情况下 C+程序员习惯在类体中只定义数据成员以及成员函数的声明,而将成员函数
14、的实现写在类外。因此类的定义由声明部分和实现部分组成。 声明部分:声明类的数据成员类型和成员函数的参数类型、个数以及返回值类型。 实现部分:对说明类成员函数的具体实现,2020/9/10,32,1.4.2 在类外定义成员函数,一、定义的格式 /类声明部分 class 类名 数据成员类型 数据成员名; 函数类型 成员函数名(参数表); ;,2020/9/10,33,1.4.2 在类外定义成员函数,/类实现部分 函数类型 类名:员函数名1(参数表) /实现 函数类型 类名:员函数名1(参数表) /实现 ,2020/9/10,34,1.4.2 在类外定义成员函数,说明: (1)在类声明部分,包括数据
15、成员的定义和成员函数的声明。 (2)成员函数的声明主要说明函数的类型,函数的参数个数及类型,并用“;”结束。 (3)函数实现部分是对在类中定义的成员函数完成功能的实现,包括函数头和函数体。在类体中直接定义函数时,不需要在函数名前面加上类名,因为函数属于哪一个类是不言而喻的。但成员函数在类外定义时,必须在函数名前面加上类名,给与限定,2020/9/10,35,1.4.2 在类外定义成员函数,(4)“”是作用域限定符或称作用域运算符,用它声明函数是属于哪个类的。如果在作用域运算符“”的前面没有类名,或者函数名前面既无类名又无作用域运算符“”,则表示函数不属于任何类,该函数不是成员函数,而是全局函数
16、,即非成员函数的一般普通函数。,2020/9/10,36,1.4.2 在类外定义成员函数,例:Cdate类定义 / Cdate类声明部分 class Cdate public: /函数声明 void Setdate (int y, int m,int d); int Isleapyear(); void Print(); private: int year,month ,day; ;,2020/9/10,37,1.4.2 在类外定义成员函数,/ Cdate类成员函数的实现 void Cdate: Setdate (int y, int m,int d) year=y; month=m; day
17、=d; ,2020/9/10,38,1.4.2 在类外定义成员函数,int Cdate:Isleapyear() return (year%4=0 ,2020/9/10,39,1.5 对象成员的引用,在程序中经常需要访问对象中的成员,访问对象中的成员可以有3种方法: 通过对象名和成员运算符访问对象中的成员; 通过指向对象的指针和指针运算符访问对象中的成员; 通过对象的引用变量访问对象中的成员。,2020/9/10,40,1.5 对象成员的引用,(1)通过对象名和成员运算符访问对象中的成员的一般形式 对象名. 数据成员名 / “.”是成员运算符 对象名. 成员函数名 例如: Cdate d1;
18、/定义一个Cdate类的对象d1 d1.Print(); /通过对象名和成员运算符访问对象中的公有成员,2020/9/10,41,1.5 对象成员的引用,(2)通过指向对象的指针和指针运算符访问对象中的成员的一般形式 对象指针名-数据成员名/“-”是指向运算符 对象指针名 - 成员函数名 例如: Cdate d,*p; /定义对象d和对象指针变量p p=/通过指向对象的指针和指向运算符访问对象中的成员,2020/9/10,42,1.5 对象成员的引用,(3)通过对象的引用变量访问对象中的成员 如果为一个对象定义了一个引用变量,它们是共占同一段存储单元的,因此可以通过引用变量来访问该对象中的成员
19、。 例如: Cdate d1; /定义对象d1 Cdate /引用变量访问对象中的成员,2020/9/10,43,/ Cdate.h 在头文件中声明日期类 class Cdate public: void Setdate (int y, int m,int d); int Isleapyear(); void Print(); private: int year,month ,day; ;,【例1.1】一个完整的Cdate类的应用程序,2020/9/10,44,/Cdate.cpp 定义成员函数实现部分 #include #include “Cdate.h” /包含类定义的头文件 void C
20、date: Setdate (int y, int m,int d) year=y; month=m; day=d; int Cdate:Isleapyear() return (year%4=0,2020/9/10,45,void main() /main.cpp 主函数 Cdate d1,d2,d3,*p; /定义对象和对象指针p Cdate ,2020/9/10,46,例1.1程序执行过程,2020/9/10,47,【例1.2】封装一个学生类,学生的信息包括学生的姓名、学号、性别、年龄和3门的成绩。可以设置学生的各类信息,统计该学生的平均成绩并输出学生信息。,Cstudent的类图,20
21、20/9/10,48,/CStudent.h 这是头文件,在此文件中进行类的声明 class CStudent /类声明 public: void setinfo(char *,int ,char,int); void setgrad(float , float , float); float avg(); void display(); private: char name20; int id ; char sex; int age; float grad3; ;,2020/9/10,49,/CStudent.cpp在此文件中进行函数的定义 #include #include #includ
22、e CStudent.h/漏写此行编译通不过 void CStudent:setinfo(char *na,int i ,char s ,int a) strcpy(name,na); id=i; sex=s; age=a; void CStudent:setgrad(float a, float b, float c) grad0=a; grad1=b; grad2=c; ,2020/9/10,50,float CStudent:avg() return (grad0+ grad1 +grad2)/3; void CStudent:display( ) coutid:idendl; cout
23、name:nameendl; coutsex:sexendl; coutage:ageendl; ,2020/9/10,51,/main.cpp主函数模块 #include #include CStudent.h/将类声明头文件包含进来 void main( ) CStudent stud1;/定义对象 stud1. setinfo(张三,2006102,m,18); stud1.setgrad(79,98,87); stud1.display(); cout 平均成绩:stud1.avg(); ,2020/9/10,52,1.6 构造函数和析构函数,构造函数和析构函数的作用 1. 构造(co
24、nstructor)函数 在创建对象时,系统自动调用它来初始化数据成员; 2. 析构(destructor)函数 在对象生存期结束的时候,自动调用来释放该对象。,2020/9/10,53,1.6.1 构造函数的定义,一、构造函数的定义格式: class 类名 public: 构造函数函数名(参数表); ;,2020/9/10,54,1.6.1 构造函数的定义,二、构造函数的特点 (1)构造函数是类的一个特殊的成员函数,函数名与类名相同; (2)构造函数的访问属性应该是公有(public)访问属性; (3)构造函数的功能是对对象进行初始化,因此在构造函数中只能对数据成员做初始化,这些数据成员一般
25、为私有成员,在构造函数中一般不做初始化以外的事情;,2020/9/10,55,1.6.1 构造函数的定义,(4)构造函数可以在类内定义也可以在类外定义; (5)构造函数无函数返回类型。注意:是什么也不写,也不可写void; (6)在程序运行时,当新的对象被建立,该对象所属的类的构造函数自动被调用,在该对象生存期中也只调用这一次。 (7)构造函数可以重载。类中可以有多个构造函数,它们由不同的参数表区分,系统在自动调用时按一般函数重载的规则选一个执行。,2020/9/10,56,【例1.3】定义Cdate一个不带参数的构造函数。 #include class Cdate/定义一个日期类 publi
26、c:/公有数据成员 Cdate()/定义构造函数 year=2000;/初始化数据成员 month=1; day=1; ,2020/9/10,57,void Print()/一般成员函数 coutyear- month -dayendl; private: int year, month ,day; ; void main() Cdate d1; /自动调用构造函数 d1.Print(); ,2020/9/10,58,【例1.4】Cdate类带参数的构造函数 #include class Cdate public: Cdate(int y, int m,int d); void Print()
27、; private: int year,month ,day; ; Cdate:Cdate(int y, int m,int d) year=y; month=m; day=d; ,2020/9/10,59,void Cdate:Print() coutyear- month -dayendl; void main() Cdate d1(1999,12,30); Cdate d2(2001,4,1); d1.Print(); d2.Print(); ,2020/9/10,60,三、使用初始化表来实现对数据成员的初始化,初始化表的一般格式: 类名:构造函数名(参数列表):初始化表 构造函数其他实
28、现代码 初始化表的格式: 对象成员1(参数名或常量),对象成员2(参数名或常量),对象成员n(参数名或常量),2020/9/10,61,三、使用初始化表来实现对数据成员的初始化,例如例1.4定义的构造函数可以改用以下形式: Cdate: Cdate(int y, int m,int d): year(y), month(m),day(d) 注意:这种写法方便、简洁。许多C+程序员喜欢用这种方式初始化所有的数据成员。除了构造函数可以使用初始化表外,类的其他成员函数也可以根据需要使用初始化表。,2020/9/10,62,1.6.2 构造函数的重载,程序中需要以不同的方式初始化类对象时,可以在一个类
29、中定义多个构造函数。即可以重载构造函数。C+定义对象时,根据声明中的参数个数和类型选择相应的构造函数初始化对象。 函数的重载。,2020/9/10,63,【例1.5】Cdate类中的重载构造函数 #include class Cdate public: Cdate();/不带参数的构造函数,又称默认构造函数 Cdate(int y);/带1个参数的构造函数 Cdate(int y, int m); /带2个参数的构造函数 Cdate(int y, int m,int d); /带3个参数的构造函数 void Print(); private: int year,month ,day; ;,20
30、20/9/10,64,Cdate: Cdate()/构造函数的定义 year=2000; month=1; day=1; Cdate: Cdate(int y) year=y; month=1; day=1; Cdate: Cdate(int y, int m) year=y; month=m; day=1; Cdate: Cdate(int y, int m,int d) year=y; month=m; day=d;,2020/9/10,65,void Cdate:Print() coutyear-month-dayendl; void main() Cdate day1; Cdate d
31、ay2(2004); Cdate day3(2005,2); Cdate day4(2006,12,16); day1.Print(); day2.Print(); day3.Print(); day4.Print(); ,2020/9/10,66,1.6.2 构造函数的重载,关于构造函数C+规定: (1)每个类必须有一个构造函数,如果没有就不能创建任何对象; (2)若没有定义任何一个构造函数,C+提供一个默认的构造函数,该构造函数没有参数,不做任何工作,相当一个空函数,例如: Cdate:Cdate() ,2020/9/10,67,1.6.2 构造函数的重载,所以在讲构造函数以前也可以定义一
32、个对象,就是因为系统提供的默认构造函数。 (3)只要C+提供一个构造函数(不一定是没有参数的),C+不再提供默认的构造函数。也就是说为类定义了一个带参数的构造函数,还想要创建无参的对象时,则需要自己定义一个默认构造函数,2020/9/10,68,1.6.3 默认参数的构造函数,为什么使用默认参数的构造函数:对象常有一些初始值。 【例1.6】设计CPoint类,它带有默认参数的构造函数。 分析:一个点包括横坐标(x)和纵坐标(y)两个数据成员, 默认初始值为(0,0)。也可以根据用户需要,初始化点为其他坐标,因此需要定义一个带默认参数的构造函数。定义成员函数print()输出该点。,2020/9
33、/10,69,2020/9/10,70,#include class CPoint public: CPoint (double x1=0,double y1=0) x=x1; y=y1; void print () cout(x,y)endl; private: double x,y; ;,程序运行结果: (0,0) (10,0) (20,30),2020/9/10,71,void main() CPoint point1; /自动调用带默认参数的构造函数 CPoint point2(10);/自动调用带默认参数的构造函数 CPoint point3(20,30);/自动调用构造函数 poi
34、nt1.print(); point2.print(); point3.print(); 注意:构造函数是对象创建时自动调用的,不能显式调用。,2020/9/10,72,一个类可以包括多个构造函数,但对每一个对象来说,对象创建时只能执行其中一个与对象参数相匹配的构造函数。下面代码存在二义性问题:,#include class CPoint public: /带默认参数的构造函数 CPoint (double x1=0,double y1=0) x=x1; y=y1; /带一个参数的构造函数 CPoint (double x1) x=x1; y=100; ,2020/9/10,73,/其他成员函
35、数 private: double x,y; ; void main() CPoint point1(10); /错误,匹配哪个构造函数不确定 point1.print(); ,2020/9/10,74,1.6.4 析构函数,一、析构函数的作用 是一个特殊类成员函数,它的作用与构造函数相反。析构函数的作用是在对象生存期结束之前自动执行,做清理工作。 例如: 一个类可能在构造函数中分配资源,这些资源要在对象的生存期结束以前释放,释放资源的工作就是自动调用类的析构函数完成的。,2020/9/10,75,1.6.4 析构函数,二、析构函数的特点 (1)析构函数函数的名字特别,是类名加“”字符,表明它
36、与构造函数相反; (2)析构函数没有参数,不能指定返回值类型; (3)一个类中只能定义一个析构函数,所以析构函数不能重载; (4)在对象生存期结束时,系统自动调用析构函数。,2020/9/10,76,1.6.4 析构函数,三、析构函数的定义格式 类名: 析构函数名() /实现代码 例如:Cdate:Cdate() ,2020/9/10,77,【例1.7】 设计一个简单的字符串类CString,类中有两个数据成员,分别表示字符串的长度和字符串的内容。定义一个构造函数和一个析构函数,成员函数GetLength( )返回字符串长度,成员函数GetContents( )获得字符串的内容,重载成员函数S
37、etContents( )可以改变字符串的值。,2020/9/10,78,2020/9/10,79,#include #include class CString public: CString(); /默认构造函数 CString(char *s);/带参数的构造函数 CString(); /析构函数 int GetLength();/得到字符串的长度 void GetContents(char *str);/得到字符串的内容 void SetContents(int len, char *cont);/重新设置字符串 void SetContents(char *cont); /重载成员S
38、etContents(),重新设置字符串,2020/9/10,80,private: int length; /字符串长度 char *contents;/字符串内容 ; CString:CString() length = 0; contents = NULL; cout 字符串对象初始化:默认构造函数 endl; CString:CString(char *s) length = strlen(s); contents = new charlength+1; strcpy(contents,s); cout 字符串对象初始化:一个参数的构造函数 endl; ,2020/9/10,81,CS
39、tring:CString() cout contents 被销毁 endl; if(contents != NULL) delete contents; int CString:GetLength() return length; void CString:GetContents(char *str) strcpy(str, contents); ,2020/9/10,82,void CString:SetContents(int len, char *cont) length = len; if(contents != NULL) delete contents; contents = n
40、ew charlen+1; strncpy(contents,cont,length); contents length=0; cout 两个参数的SetContents函数 endl; ,2020/9/10,83,void CString:SetContents( char *cont) length = strlen(cont); if(contents != NULL) delete contents; contents = new charlength+1; strcpy(contents,cont); cout 一个参数的SetContents函数 endl; void main()
41、 CString str1,str2; CString str3(第三个字符串); str1.SetContents(第一个字符串); str2.SetContents(20, 第二个字符串两个参数,2020/9/10,84,int i = str1.GetLength(); char string100; str1.GetContents(string); cout i string endl; i = str2.GetLength(); str2.GetContents(string); cout i string endl; i = str3.GetLength(); str3.GetC
42、ontents(string); cout i string endl; ,2020/9/10,85,1.6.4 析构函数,四、构造函数和析构函数的调用时间和调用顺序 构造函数在创建对象时自动调用,调用的顺序是按照对象定义的次序。析构函数的调用顺序正好与构造函数相反。也就是说对于同一存储类别的对象是先构造的对象后析构,后构造的对象先析构。,2020/9/10,86,1.6.5 拷贝构造函数和默认拷贝构造函数,一、拷贝构造函数的作用 用一个已知的对象来初始化另一个对象 二、拷贝构造函数定义格式 类名:拷贝构造函数名(类名 /形参是一个const的对象引用,2020/9/10,87,1.6.5 拷
43、贝构造函数和默认拷贝构造函数,三、通常在下述三种情况下,需要用拷贝初始化构造函数: (1)明确表示由一个对象初始化另一个对象时;如Cdate day3(d1); (2)当对象作为函数实参传递给函数形参时;如fun(Cdate day); (3)当对象作为函数的返回值,创建一个临时对象时。,2020/9/10,88,【例1.8】设计一个复数类,两个数据成员分别表示复数的实部(real)和虚部(imag),2个构造函数分别在不同的情况下初始化对象,函数Print()用于输出复数。,#include class CComplex public: CComplex(double, double); C
44、Complex(CComplex ,2020/9/10,89,CComplex:CComplex(double r=0.0, double i=0.0) real = r; imag = i; cout调用两个参数的构造函数endl; CComplex:CComplex (CComplex ,2020/9/10,90,void CComplex:Print()/ 显示复数值 cout ( real , imag ) endl; void f(CComplex n) /对象作为函数参数 coutn=; n. Print(); CComplex CComplex:add(CComplex /调用复
45、数类的拷贝构造函数 ,2020/9/10,91,void main(void) CComplex a(3.0,4.0), b(5.6,7.9); CComplex c(a); /调用复数类的拷贝构造函数 cout a = ; a.Print(); cout c = ; c.Print(); f(b); /对象作为函数实参传递给函数形参 c=a.add(b); /对象作为函数返回值,调用拷贝构造函数 c.Print (); ,2020/9/10,92,调用拷贝构造函数各对象数据成员变化,2020/9/10,93,1.6.5 拷贝构造函数和默认拷贝构造函数,当用户自定义了拷贝构造函数,所用一个对象
46、创建另一个对象时,系统自动调用了用户自定义拷贝构造函数。如果用户没有自己定义拷贝构造函数,那么编译系统会自动会提供一个默认的拷贝构造函数。 四、默认拷贝构造函数 默认的拷贝构造函数所做的工作是将一个对象的全部数据成员赋值另一个对象的数据成员。C+把这种只进行对象数据成员简单赋值,称之为“浅拷贝”,2020/9/10,94,【例1.9】 设计一个班级类CClass,两个数据成员name和num分别表示班级的名称和人数。函数Print()输出班级名称和班级人数。,#include #include class CClass public: CClass (char *cName=,int snum
47、=0); CClass () cout析构班级:pnameendl; delete pname; ,2020/9/10,95,void Print(); private: char * pname; int num; ; CClass :CClass (char *cName,int snum) int length = strlen(cName); pname = new charlength+1; if (pname!=0) /或pname!=NULL strcpy(pname,cName); num=snum; cout创建班级:pnameendl; ,2020/9/10,96,void
48、 CClass : Print() coutpname班的人数为:numendl; void main() CClass c1(计算机061班,56); CClass c2 (c1); c1.Print(); c2.Print(); ,2020/9/10,97,c1、c2内存分配情况(浅拷贝),2020/9/10,98,问题解决 : CClass (CClass ,2020/9/10,99,c1、c2内存分配情况(深拷贝),2020/9/10,100,1.7 类和对象的进一步应用,1.7.1 堆对象 1.7.2 对象数组 1.7.3 类对象作为成员 1.7.4 面向对象程序中的常量,2020/
49、9/10,101,1.7.1 堆对象,用new和 delete运算符定义堆对象的格式 类名 *p p=new 类名; delete p; #include”Cdate.h” void main() Cdate *dp1,*dp2; /定义两个对象指针 dp1=new Cdate;/分配堆内存,初始化堆对象的数据成员,2020/9/10,102,dp2=new Cdate(2006,12,1); /调用带3个参数的构造函数,初始化堆对象的数据成员 dp1- Print(); /通过指针引用对象成员,输出日期200-1-1 (*dp2).Print(); /通过指针指向的对象引用对象成员,输出日期
50、2006-12-1 delete dp1;/调用dp1的析构函数 delete dp2;/调用dp2的析构函数 ,2020/9/10,103,1.7.2 对象数组,对象数组中的每一个元素都是类的对象 一、声明一维对象数组的语法形式 类名 数组名常量表达式; 注意:在建立数组时,要调用构造函数初始化每个数组元素。 CStudent s3 = CStudent(张三,2006001,19); CStudent(李四,2006002,18); CStudent(“王五”,2006003,20; 二、引用对象数组元素的公有成员: 数组名下标 . 成员名;,2020/9/10,104,【例1.10】 设
51、计一个学生类,假设一个班有5个学生,计算这个班学生的平均年龄。,#include #include class CStudent public: CStudent(char *na,int i ,int a); int GetAge(); private: char name20; int id;int age; ;,2020/9/10,105,CStudent:CStudent(char *na,int i ,int a) strcpy(name, na); id=i; age = a; int CStudent:GetAge() return age; ,2020/9/10,106,voi
52、d main() int sum=0; CStudent s5 = CStudent(张三,10001, 20), /对象数组初始化 CStudent(李四,10002, 22 ), CStudent(王五,10003, 24 ), CStudent(赵六,10004, 26 ), CStudent(孙六,10005, 28 ); for(int i=0; i5; i+) sum += si.GetAge(); /累加每个学生的年龄 cout sum/5 endl; ,2020/9/10,107,1.7.3 类对象作为成员,有类对象作为成员称为组合类 一、通过构造函数的初始化表为内嵌对象初始化
53、 格式为: 类名:构造函数(参数表):内嵌对象1(参数表1),内嵌对象2(参数表2), 构造函数体 ,2020/9/10,108,1.7.3 类对象作为成员,二、组合类构造函数的执行顺序为: (1)按内嵌对象的声明顺序依次调用内嵌对象的构造函数 (2)然后执行组合类本身的构造函数。 【例1.11】设计一个学生类。数据成员包括学生的姓名、学号、性别、出生日期。 分析:学生的姓名、性别可以用简单的数据类型表示,学生的学号和出生日期可以用类对象表示。定义三个类:学生类、日期类和学号类。学生类是一个组合类,类的数据成员包括其他类对象,因此学生类的构造函数中使用初始化表初始化类对象数据成员。,2020/
54、9/10,109,2020/9/10,110,#include #include /日期类声明 class Cdate public: Cdate(int y=1985, int m=1,int d=1) year=y; month=m;day=d; cout调用日期类的构造函数endl; Cdate(Cdate ,2020/9/10,111, Cdate() cout调用日期类的析构函数endl; private: int year,month ,day; ; /学号类声明 class CStudentID public : CStudentID(int i) value=i; cout构造
55、学号valueendl; ,2020/9/10,112,CStudentID() cout析构学号valueendl; private: int value; ; class CStudent /学生类声明 public: CStudent (char*,char,int, Cdate ,2020/9/10,113,private: char name20; char sex; CStudentID id ; Cdate birthday; ; CStudent:CStudent(char *na, char s,int i, Cdate ,2020/9/10,114,CStudent: CS
56、tudent () cout调用学生 name的析构函数endl; void main( ) Cdate day1(2000,1,1); /定义学生对象 CStudent stud1(张三, m, 2006102, day1); ,2020/9/10,115,1.7.4 面向对象程序中的常量,一、常对象 1.定义 如果希望某个对象的所有成员在程序中不能被修改,可以将此对象定义为“常对象”。 2.定义常对象的一般形式为 类名 const 对象名(实参列表); const 类名 对象名(实参列表); 例如:一个日期对象始终表示2000年5月1号,可以定义为: Cdate const d1(2000
57、,5,1); /d1是常对象,2020/9/10,116,1.7.4 面向对象程序中的常量,注意: d1是常对象,在所有的场合中,对象d1中的所有成员的值都不能被修改。定义常对象必须要有初值。以下语句是错误的: Cdate d1(2000,5,1); /一般对象 Cdate const d2 ; / d2是常对象 d2=d1; /错误,常对象必须在定义的时候赋初值 如果一个对象被声明为常对象,则不能调用该对象的非const型的成员函数 例如,对于例1.5中已定义的Cdate类,如果有 const Cdate d1(2001,5,1); /定义常对象d1 d1. Print(); /非法,2020/9/10,117,1.7.4 面向对象程序中的常量,常对象只能访问常成员函数,而不能访问非常成员函数。如果希望成员函数可引用常对象中的数据成员,只需将该成员
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年成都市青羊区中小学教师招聘笔试参考试题及答案详解
- 初升高完美衔接教材 英语教学 名词和代词
- 2026年阜新市新邱区中小学教师招聘笔试备考题库及答案详解
- 2026年河北省沧州市中小学教师招聘考试备考题库及答案详解
- 2026年北京市门头沟区街道办人员招聘笔试备考题库及答案详解
- 2026年杭州市余杭区街道办人员招聘笔试参考题库及答案详解
- 2026年本溪市溪湖区中小学教师招聘笔试备考试题及答案详解
- 2026年徐州市鼓楼区街道办人员招聘考试备考题库及答案详解
- 2026年枣庄市台儿庄区街道办人员招聘笔试模拟试题及答案详解
- 浙江省杭州市临安区2027届数学六上期末监测试题含解析
- 2026新疆乌鲁木齐市政环卫集团有限公司面向社会招聘5人考试备考题库及答案详解
- 2026年新教材人教版九年级上册英语Unit 3 Smart Learning 教案
- 2025南瑞集团有限公司招聘300人笔试历年常考点试题专练附带答案详解
- 2026贵州铜仁德江机场消防员岗招聘15人笔试备考试题及答案详解
- 2026年抖音内衣-泳衣类目准入考试高频原题+标准答案
- 2024年四川省农作物植保员技能竞赛参考试题库(含答案)
- 分层审核检查表(一)
- 建筑材料与检测说课
- 病理科建设与管理指南
- 七年级数学 去括号
- GB/T 9780-2013建筑涂料涂层耐沾污性试验方法
评论
0/150
提交评论