经典C学习经验分享.ppt
《经典C学习经验分享.ppt》由会员分享,可在线阅读,更多相关《经典C学习经验分享.ppt(80页珍藏版)》请在三一文库上搜索。
1、C+面向对象程序设计 第三章 再论类和对象,第一章 C+的初步知识 第二章 类和对象 第三章 再论类和对象 第四章 运算符重载 第五章 继承与派生 第六章 多态性与虚函数 第七章 输入输出流 第八章 C+工具,3.1 构造函数 3.2 析构函数 3.3 调用构造函数和析构函数的顺序 3.4 对象数组 3.5 对象指针 3.6 共用数据的保护 3.7 对象的动态建立和释放 3.8 对象的赋值和复制 3.9 静态成员 3.10 友元 3.11 类模板,3.1 构造函数,对象的初始化 和普通变量一样,我们定义一个变量,往往同时进行初始化: int a = 3; 而声明类时,数据成员不能进行初始化:
2、class time int hour = 0; int minute = 0; int second = 0; 因为类不是实体,不占分配存储空间,显然无法容纳数据。,3.1 构造函数,如果一个类的所有数据成员都是公用的,我们可以象结构体变量那样,在定义对象时(而不是声明类时)进行初始化: class time public: int hour ; int minute; int second; ; time t1 = 13,30,20; 但在类的声明中,数据成员往往都是私有的,不能这样初始化。就需要一个公有成员函数来完成,而且应该是自动调用地完成。这就是构造函数。,3.1 构造函数,构造函数
3、的作用 C+提供了构造函数( constructor )来处理对象的初始化。构造函数是一个由用户定义的特殊的成员函数。与其他成员函数不同之处在于: 用户不能调用它,而是在定义对象时,有系统自动调用构造函数。 构造函数的名字必须与类名一致,不能是其他名字。 构造函数不能有任何返回类型。 用户如果没有定义构造函数,系统会自动生成一个构造函数,只不过函数体中没有任何语句。,3.1 构造函数,例3.1 将前例的时间类定义构造函数。在构造函数中加入输出语句,看看运行效果。,class time private: int hour, minute, second; public: time ( ) /ti
4、me 类的构造函数 hour = 0; minute = 0; second = 0; void setTime ( ); void showTime ( ) cout hour “:“ minute “:“ second endl; ;,void time:setTime ( ) couthour; coutminute; coutsecond; void main ( ) time t1; / 定义time类对象t1,调用构造函数tume ( ) t1.setTime( ); t1.showTime ( ); time t2; / 定义time类对象t2,调用构造函数tume ( ) t2
5、.setTime ( ); t2.showTime ( ); ,3.1 构造函数,带参数的构造函数 前一个示例中,每产生一个time了的对象,其初值都初始化为0。如果用户初始化时,不想将对象初值置为0而是其它值,就需要用带参数的构造函数来实现。 声明一个构造函数的一般格式为: 构造函数名 ( 类型1 形参1,类型2 形参2,); 定义一个对象的一般格式为: 类名 对象名 ( 实参1,实参2, ); 下面举例说明用法。,3.1 构造函数,例3.2 :有两个长方体,长宽高分别为(1,2,3)和(4,5,6)。试编写一基于对象的程序,分别求他们的体积,并且要求用带参数的构造函数初始化他们。,#inc
6、lude class box private: int height, width, length; public: box ( int h, int w, int len ) height = h; width = w; length = len; int volume ( ) return height * width * length; ;,void main ( ) box box1 (1,2,3); cout “box1的体积为“ box1.volume( ) endl; box box2 (4,5,6); cout “box2的体积为“ box2.volume( ) endl; ,
7、3.1 构造函数,用参数初始化表对数据成员初始化 C+提供另一种初始化数据成员的方法:参数初始化表来实现对数据成员的初始化。这种方法不在函数体内初始化数据成员,而是在函数首部实现。例3.2 我们改写成如下形式:,#include class box private: int height, width, length; public: box(int h,int w,int len):height(h),width(w),length(len) int volume ( ) return height * width * length; ; void main ( ) box box1 (1,
8、2,3); cout “box1的体积为“ box1.volume( ) endl; box box2 (4,5,6); cout “box2的体积为“box2.volume( ) endl; ,3.1 构造函数,示例中的初始化表表示,用形参h的值初始化数据成员height,用w值初始化width,用len值初始化 length。这种初始化方法比较简练,可以直接在类体中定义构造函数。,3.1 构造函数,构造函数的重载 一个类中,可以有多个构造函数,只要他们的参数表不同。以方便同类对象不同初始化的需要。见下例3.3 :,#include class circle private: float r
9、adius; public: circle( ); / 声明一个无参数构造函数 circle( float r ): radius (r) / 声明一个带参数构造函数 float area ( ) return radius * radius * 3.14159; ; circle:circle ( ) radius=10.0; void main ( ) circle c1 ( 1.0 ), c2; cout “c1的面积为“ c1.area( ) endl; cout “c2的面积为“ c2.area( ) endl; ,3.1 构造函数,说明 参数表为空的构造函数叫默认构造函数,一个类中
10、只能有一个默认函数。 定义对象时,如果想用默认构造函数初始化它,正确的定义形式为: circle c2; 而不是: circle c2 ( ); 一个类尽管定义了多个构造函数,一个对象只能用其中一个来初始化。,3.1 构造函数,使用默认参数的构造函数 构造函数的参数既可以通过实参传送,也可以指定为某些默认值。当用户不指定实参值时,编译系统便将默认值为形参值。 在实际生活中,常有一些这样的默认值。如计数器的默认值为0;战士的性别默认值为“男“;男性职工退休年龄默认值为60岁等,如果实际情况不是默认值,则由用户另外指定。采用默认值,可以减少用户的输入量。 下面举例说明。,3.1 构造函数,例3.4
11、 试将例3.3 的构造函数改用默认值的参数,半径值默认为1.0。,#include class circle private: float radius; public: circle( float r = 1.0 ); / 声明构造函数是指定默认参数 float area ( ) return radius * radius * 3.14159; ; circle:circle ( float r ) /定义函数时,可不再指定默认参数 radius = r; void main ( ) circle c1 (10.0), c2; cout “c1的面积为“ c1.area( ) endl;
12、cout “c2的面积为“ c2.area( ) endl; ,3.1 构造函数,构造函数中使用默认参数的好处 提供建立对象时的多种选择,相当于好几个重载的构造函数。 即使在调用构造时不提供参数也不会出错,因为有默认参数值参与对象初始化。 当每一个对象都是相同的初始值时,非常方便,用户不需要输入数据。,3.1 构造函数,默认参数值的构造函数使用注意 何处指定默认参数值?构造函数的声明处还是定义处?应该在构造函数的声明处指定默认参数值。因为类的声明在头文件中,用户是看得见的,而防在函数的定义处,用户不一定看得见。 一个类定义了全部是默认参数的构造函数后,不能再定义重载的构造函数。否则会产生多义性
13、,系统不知道调用哪一个。例如一个类有右边形式 的三个重载构造函数,若定义了如 下对象: circle circle1; 它调用哪一个构造函数呢?系统不 能确定,从而引起混乱。,circle ( float r=2.3 ); circle ( ); circle ( float );,3.2 析构函数,什么是析构函数? 析构函数( destructor ) 也是一个特殊函数,它的作用与构造函数相反,是在撤消对象占用的内存前进行一些清理工作。它还可以被用来执行“用户希望在最后依次使用对象之后所执行的任何操作“。 析构函数的名称是类名的前面加一个取反符号“。我们在类的声明中定义析构函数。如果用户不定
14、义析构函数,系统便自动生成一个空的析构函数。 析构函数特点: 没有返回类型; 没有函数参数; 不能被重载。,3.2 析构函数,什么时候运行析构函数? 当对象的生命结束时,会自动执行它的析构函数。具体而言,当出现以下几种情况,析构函数就会被执行。 如果在函数中定义了一个对象,当函数调用结束时,释放对象,释放对象前自动执行析构函数。 static 局部对象在函数调用结束时,包含的对象不会被释放,只在main函数结束或调用exit函数时,才调用static局部对象的析构函数。 如果定义了一个全局对象,则在程序的流程离开其作用域时(如main函数结束,或exit语句),调用该全局对象的析构函数。 如果
15、用new运算符动态地建立了一个对象,当用delete 运算符释放对象时,先调用该全局对象的析构函数。,3.2 析构函数,#include class box private: int height, width, length; public: box ( int h, int w, int len ) height = h; width = w; length = len; box ( ) / 析构函数 cout “Destructoring a object“ endl; int volume ( ) return height * width * length; ;,void main
16、( ) box box1 (1,2,3); cout “box1的体积为“ box1.volume( ) endl; box box2 (4,5,6); cout “box2的体积为“ box2.volume( ) endl; ,例3.5 析构函数举例。,3.3 调用构造函数和析构函数的顺序,调用构造函数和析构函数的顺序 先构造的后析构,后构造的先析构。,例: C3-5-1.CPP,3.3 调用构造函数和析构函数的顺序,注意:先构造的后析构,后构造的先析构,并非绝对成立! 对象不同的作用域,不同的存储类别,那么调用构造函数和析构函数的时候也有所不同. 例如: 一个程序中有多个文件,在多个文件中
17、定义了全局对象,那么这些对象的执行顺序是不确定的 在函数中定义局部自动对象,如果函数被多次调用 如果函数中定义静态局部对象,那么函数调用结束时对象并不释放,只有main结束或调用exit中才调用析构函数. Void fn() Student s1; static Student s2; 例: C3-5-2.CPP,3.4 对象数组,数组不仅可以由简单变量组成,也可以由对象组成,即每一个数组元素都是同类的对象。 例如,一个班有30人,每个学生的属性包括学号、姓名、性别。我们建立起学生类后,为每个学生建立一个对象,需要分别取30个对象名,很不方便。较好的做法是,定义一个“学生类“,的对象数组,每一
18、个数组元素是一个“学生类“的对象。 例如: Student stud30;,3.4 对象数组,在建立对象数组时,同样调用构造函数。 如果构造函数只有一个参数,在定义数组时可以在等号后面花括号内提供实参。 Student stud3=60,70,80; 实参个数不能超过数组元素个数,因为编译系统只为每个对象元素的构造函数传递一个实参 Student stud3=60,70,80,90;/不合法 如果构造函数有多个参数,则不能用在定义数组时直接提供所有实参的方法。 例如: Student:Student(int=1001,int=18,int=60)/构造函数 Student stud3=111,
19、34,31; 这种使用方式关系不清晰,出现歧义性,3.4 对象数组,构造函数有多个参数时,如下实现对数组对象的初始化. Student Stud3=Student(11,32,74), Student(12,34,27), Student(14,45,63) ; 如下面的例子.,3.4 对象数组,例:3.6-1.cpp,#include #include using namespace std; class student private: int num; string name; char sex; public: student( int n, string nam, char s )
20、num = n; name=nam; sex = s; cout “Constructor called.“ endl; student ( ) cout “Destructor called.“ endl; void display ( ); ;,void student:display ( ) cout“num:“numendl; cout“name:“nameendl; cout“sex:“; if (sex=0) cout“男“endl; else cout“女“endl; void main( ) student stud3 = student(1001,“张三“,1), stude
21、nt(1002,“李四“,0), student(1003,“王五“,0) ;/用指定参数的构造函数初始化数组 cout “第一个学生“ ; stud0.display( ); cout “第二个学生“ ; stud1.display( ); cout “第三个学生“ ; stud2.display( ); ,3.4 对象数组,例:C3-6.CPP,#include using namespace std; class Box public: Box(int h=10,int w=12,int len=15):height(h),width(w),length(len) int volume(
22、); private: int height; int width; int length; ;,int Box:volume() return(height*width*length); int main() Box a3= Box(10,12,15), Box(15,18,20), Box(16,20,26) ; cout“volume of a0 is “a0.volume()endl; cout“volume of a0 is “a1.volume()endl; cout“volume of a0 is “a2.volume()endl; return 0; ,3.5 对象指针,指向对
23、象的指针 创建一个类的对象时,系统会为每一个对象分配一定的存储空间,以存放成员。对象空间的起始地址就是对象的指针。可以定义一个指针,用来存放对象的指针. 格式: 类名 *对象指针名;,3.5 对象指针,指向对象的指针 例:c3-point.cpp 访问成员的方法:( *pt ).hour, (*pt).put ( ) 或者:pt-hour, pt-put( ),class Time public: int hour, minute, sec; void put ( ) hour = 12; minute = 0; sec = 0; ;,void main ( ) Time *pt, t1; p
24、t = ,3.5 对象指针,指向对象数据成员的指针 定义一个指向对象数据成员的指针变量的方法和前面介绍的定义指向普通变量的指针变量方法相同。 定义格式:数据类型名 * 指针变量名; 例如: int *pl; / 定义指向整形数据的指针变量 pl= / 输出t1.hour的值,3.5 对象指针,指向对象成员函数的指针 定义指向对象成员函数的指针变量的方法和定义指向普通函数的指针变量的方法有所不同。 指向普通函数的指针变量的定义方法: 返回数据类型 (*指针变量名) (参数表列); 例:void (*p) ( ); / p是指向void 类型函数的指针变量 p = fun; / 将fun函数的入口
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 经典 学习 经验 分享
链接地址:https://www.31doc.com/p-3169766.html