1、第九章类和对象 类与对象 传统的结构化语言都是采用面向过程的方法来解决问题。在面向过程的程序设计方法中,代码和数据是分离的,因此,程序的可维护性较差。 面向对象(Object Oriented)程序设计方法则是把数据及处理这些数据的函数封装到一个类中,类是C+的一种数据类型,而使用类的变量则称为对象。 函数是将逻辑上有关的语句和数据集合在一起,主要用于执行;而类则是逻辑上有关的函数及其数据的集合,它主要不是用于执行,而是提供所需要的资源。 1 类的定义 在使用一个类之前必须先定义类。 例如在C语言里声明一个结构体类型: struct student int num char name10; c
2、har sex; ; struct student student1, student2; 现在我们声明一个类: class stud / 以class开头 int num char name10; char sex; / 以上3行是数据成员 void display() / 这是成员函数 cout”num:”numendl; cout”name:”nameendl; cout”sex:”sexendl; / 以上4行是操作代码 ; stud stud1, stud2; / 定义了两个stud类的对象 定义一个类的语法格式如下: class 类名:基类名 private: 私有成员数据及函数;
3、 protected: 保护成员数据及函数; public: 公共成员数据及函数; 类的对象声明; 一个类含有私有成员(private)、保护成员(protected)和公共成员(public)三部分。默认时在类中定义的项都是私有的。私有变量和函数只能被该类本身的成员函数存取或调用;保护成员除可以被本类中的成员函数访问外,还可以被本类派生的类的成员函数访问,因此用于类的继承;公共成员可以被本类以外的函数访问,是类与外部的接口。 类是面向对象程序设计最基本的单元,在设计面向对象程序时,首先要以类的方式描述实际待解决的问题,也就是将问题所要处理的数据定义成类的私有或公共类型的数据,同时将处理问题的
4、方法定义成类的私有或公有的成员函数。 类也可以嵌套声明。 对象 对象是声明为类类型的一个数据项,是类的实际变量,有时也称为类的实例(Instance)。 方法: 类中的成员函数称为“方法”, “方法”是对数据的操作。 方法的具体实现既可以在类的定义内部完成,也可以在类的定义之外进行,而且方法的具体实现既可以和类的定义放在同一个源文件中,也可以放在不同的源文件中。 消息: 外界是通过发“消息”来激活有关方法的。所谓“消息”,其实就是一个命令,由程序语句来实现。例如想输出对象stud1中的学生学号、姓名、性别等信息,可以在程序中写 stud1display(); 这就是向对象stud1发出的一个“
5、消息”,通知它执行display“方法”。例 1-1 : Lt1-1.cpp# include # include const double ANG_TO_RAD=0.0174532925; / 定义弧度和度之间的转换比例,即弧度的值class angle / 定义类angle double value; / 类angle的私有数据成员 public: / 类angle的公共数据成员 void SetValue(double); double GetSine(void);deg; / 声明类angle的对象degvoid angle:SetValue(double a) /类angle的成员函
6、数SetValuede的具体实现 value=a;double angle:GetSine(void) /类angle的成员函数GetSine 的具体实现 double temp; temp=sin(ANG_TO_RAD*value); return temp;void main() deg.SetValue(60.0); / 给类angle的成员变量Value赋值 coutThe sine of the angle is:; coutdeg.GetSine()endl; / 输出正弦值运行结果为:The sine of the angle is:0.866025又例:# include #
7、include const double ANG_TO_RAD=0.0174532925; / 定义弧度和度之间的转换比例,即弧度的值class angle / 定义类angle double value; / 类angle的私有数据成员 public: / 类angle的公共数据成员 void SetValue(double); double GetSine(); / void可以不要deg; / 声明类angle的对象degvoid angle:SetValue(double a) / 类angle的成员函数SetValuede 的具体实现 value=a;double angle:Get
8、Sine() / 类angle的成员函数GetSine 的具体实现 double temp; temp=sin(ANG_TO_RAD*value); return temp;void main() deg.SetValue(60.0); / 给类angle的成员变量Value赋值 coutThe sine of the angle is:; coutdeg.GetSine()endl; / 输出正弦值运行结果为:The sine of the angle is:0.8660252 内联函数 调用函数时需要一定的时间,如果有的函数需要频繁使用,则所用时间会很长,从而降低程序的执行效率。C+提供一
9、种提高效率的方法,即在编译时将调用函数的代码嵌入到主调函数中。这种嵌入到主调函数中的函数称为“内联函数”(inline function),又称“内嵌函数”或“内置函数”。例 1-2 : Lt1-2.cpp# include inline int max(int a, int b, int c) /这是一个内联函数,求3个整数中的最大者 if (ba) a=b; if (ca) a=c; return a;void main() int i=7, j=10, k=25, m; m=max(i,j,k); coutmax= mendl;运行结果为:max= 25 类的方法也可以声明和定义成内联函
10、数。可以使用下面两种格式定义类的内联函数: (1)把函数原型声明和方法的定义合并,放入类定义中。例 1-3: Lt1-3.cpp# include # include const double ANG_TO_RAD=0.0174532925;class angle / 定义类angle double value, temp; / 定义私有数据成员 public: double GetSine(double a) / 定义内联函数 value=a; temp=sin(ANG_TO_RAD*value); return temp; deg;void main() coutThe sine of t
11、he angle is: ; coutdeg.GetSine(60.0)endl;运行结果为:The sine of the angle is: 0.866025 (2)当在函数的外部定义时,把关键字inline加在函数定义之前。例 1-4 : Lt1-4.cpp# include # include const double ANG_TO_RAD=0.0174532925; / 定义弧度和度之间的转换比例,即弧度的值class angle / 定义类angle double value; / 类angle的私有数据成员 public: / 类angle的公共数据成员 void SetValu
12、e(double); double GetSine(void);deg; / 声明类angle的对象deginline void angle:SetValue(double a) / 定义内联函数 value=a;inline double angle:GetSine(void) / 定义内联函数 double temp; temp=sin(ANG_TO_RAD*value); return temp;void main() deg.SetValue(60.0); / 给类angle的成员变量Value赋值 coutThe sine of the angle is:; coutdeg.GetS
13、ine()endl; / 输出正弦值运行结果为:The sine of the angle is:0.8660253 构造函数和析构函数构造函数 在建立一个对象时,常常需要做某些初始化的工作(例如对数据赋予初值),C+提供了一种特殊的成员函数-构造函数(constructor)。这种函数与其他成员不同,不需要用户发“消息”来激活它,而是在建立对象时自动执行。构造函数是由用户定义的,它必须与类名同名,以便系统能识别它并把它作为构造函数。 下面是一个不带构造函数的类: class stud / 以class开头 int num char name10; char sex; / 以上3行是数据成员
14、void display() / 这是成员函数 cout”num:”numendl; cout”name:”nameendl; cout”sex:”sexendl; / 以上4行是操作代码 ; stud stud1; / 定义了两个stud类的对象 现在我们在其中加入构造函数: class stud / 以class开头 int num; char name10; char sex; / 以上3行是数据成员 public: stud() / 定义构造函数,函数名与类名相同 num=10010; strcpy(name,”Wang_li”); sex=F; / 以上3行为给数据赋初值 void
15、display() / 定义成员函数 cout”num:”numendl; cout”name:”nameendl; cout”sex:”sexendl; / 以上3行是操作代码 ; stud stud1; / 在定义对象stud1时自动执行构造函数 构造函数不需用户调用,而是在定义一个对象时由系统自动执行,而且只能执行一次。构造函数一般声明为public,无返回值,也不需加void类型声明。 下面写成一个完整的程序:例 1-5: 建立一个对象,输出学生的学号、姓名、性别。 Lt1-5.cpp# include # include void main() class stud / 声明一个类
16、private: int num; char name10; char sex; / 以上3行是数据成员 public: stud() / 定义构造函数,函数名与类名相同 num=10010; / 给数据赋初值 strcpy(name,Wang_li); sex=F; / 以上3行为给数据赋初值 void display() / 定义成员函数,输出对象的数据 coutnum: numendl; coutname: nameendl; coutsex: sexendl; / 以上3行是操作代码 ; stud stud1; / 在定义对象stud1时自动执行构造函数 stud1.display()
17、; / 从对象外面调用display函数运行结果为:num: 10010name: Wang_lisex: F 如果要建立两个对象,分别对数据赋予初值,可将程序修改如下:例 1-6: 建立一个对象,输出学生的学号、姓名、性别。 Lt1-6.cpp# include # include void main() class stud / 声明一个类 private: int num; char name10; char sex; / 以上3行是数据成员 public: stud(int n, char nam, char s) /定义构造函数,函数名与类名相同,有形参 num=n; / 给数据赋初
18、值 strcpy(name,nam); sex=s; / 以上3行为给数据赋初值 void display() / 定义成员函数,输出对象的数据 coutnum: numendl; coutname: nameendl; coutsex: sexendl; / 以上3行是操作代码 ; stud stud1(10010,Wang_li,f), stud2(10011,Zhang_fun,m); / 在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参 stud1.display(); stud2.display(); / 从对象外面调用display函数,分别输出两个学生的数据运
19、行结果为:num: 10010name: Wang_lisex: fnum: 10011name: Zhang_funsex: m析构函数 析构函数(destructor)与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后”的工作,通常用于释放分配给对象的存储空间。 析构函数也是类中的特殊成员函数,与定义它的类具有相同的名字,但要在前面加上一个波浪号(),以区别于构造函数。析构函数没有参数,也没有返回值,而且也不能重载,因此一个类中只能有一个析构函数。 和构造函数一样,如果在类的定义中不定义析构函数,编译系统将为之产生一个默
20、认的析构函数,对于大多数类来说,默认的析构函数就能满足要求。若在一个对象完成其操作之前还需要做一些内部处理,则应定义析构函数。例1-7: 包含构造函数和析构函数的C+程序。 Lt1-7.cpp# include # include class stud / 声明一个类 private: int num; char name10; char sex; / 以上3行是数据成员 public: stud(int n, char nam, char s) /定义构造函数,函数名与类名相同,有形参 num=n; / 给数据赋初值 strcpy(name,nam); sex=s; / 以上3行为给数据赋初
21、值 stud() / 定义析构函数 coutThis is a destructorendl; void display() / 定义成员函数,输出对象的数据 coutnum: numendl; coutname: nameendl; coutsex: sexendl; / 以上3行是操作代码 ;void main() stud stud1(10010,Wang_li,f), stud2(10011,Zhang_fun,m); / 在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参 stud1.display(); stud2.display(); / 从对象外面调用disp
22、lay函数,分别输出两个学生的数据运行结果为:num: 10010name: Wang_lisex: fnum: 10011name: Zhang_funsex: mThis is a destructorThis is a destructor 在本例中,析构函数并无任何实质上的作用,只是为了说明析构函数的使用方法。例1-8: 包含构造函数和析构函数的C+程序。 Lt1-8.cpp# include # include class stud / 声明一个类 char *p; private: int num; char name10; char sex; / 以上3行是数据成员 public
23、: stud(int n, char nam, char s) /定义构造函数,函数名与类名相同,有形参 p=new char50; num=n; / 给数据赋初值 strcpy(name,nam); sex=s; / 以上3行为给数据赋初值 stud() / 定义析构函数 coutThis is a destructor, delete the pendl; delete p; void display() / 定义成员函数,输出对象的数据 coutnum: numendl; coutname: nameendl; coutsex: sexendl; / 以上3行是操作代码 ;void ma
24、in() stud stud1(10010,Wang_li,f), stud2(10011,Zhang_fun,m); / 在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参 stud1.display(); stud2.display(); / 从对象外面调用display函数,分别输出两个学生的数据运行结果为:num: 10010name: Wang_lisex: fnum: 10011name: Zhang_funsex: mThis is a destructor, delete the pThis is a destructor, delete the p 以上程序
25、中,成员函数是在类中定义的,如果成员函数的数目很多以及函数的长度很长,类的声明就会占很大的篇幅,不利于阅读程序。可以在类的外面定义成员函数,而在类中只用函数的原型作声明。例1-9: 在类的外面定义成员函数。 Lt1-9.cpp# include # include class stud / 声明一个类 char *p; private: int num; char name10; char sex; / 以上3行是数据成员 public: stud(int n, char nam, char s); / 对构造函数的原型声明 stud(); / 对析构函数的原型声明 void display(
26、); / 对成员函数display的原型声明;stud:stud(int n, char nam, char s) / 对构造函数的定义,函数名与类名相同,有形参 p=new char50; num=n; / 给数据赋初值 strcpy(name,nam); sex=s; stud:stud() / 对析构函数的定义 coutThis is a destructor, delete the pendl; delete p;void stud: display() / 对成员函数display的定义,输出对象的数据 coutnum: numendl; coutname: nameendl; co
27、utsex: sexendl; / 以上3行是操作代码void main() stud stud1(10010,Wang_li,f), stud2(10011,Zhang_fun,m); / 在定义对象stud1、stud2时自动执行构造函数,同时给出相应实参 stud1.display(); stud2.display(); / 从对象外面调用display函数,分别输出两个学生的数据运行结果为:num: 10010 name: Wang_lisex: fnum: 10011name: Zhang_funsex: mThis is a destructor, delete the pThis is a destructor, delete the p 4拷贝构造函数 拷贝构造函数是一种特殊的构造函数,其形参是本类对象的引用。其作用是使用一个已经存在的对象去初始化另一个同类的对象。 拷贝构造函数具有以下特点: 因为该函数也是一种构造函数,所以其函数名与类名相同,并且该函数也没有返回值类型。 该函数只有一个参数,并且是同类对象的引用。 每个类都必须有一个拷贝构造函数。程序员可以根据需要定义特定的拷贝构造函数,以实现同类对象之间数据成员的传递。如果程序员没有定义类的拷贝构造函数,系统就会自动生成一个缺省的拷贝构
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1