资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,C+,面向对象程序设计,第一讲,第一章,C+,的初步知识,第二章 类和对象,第三章 关于类和对象的进一步讨论,第四章 运算符重载,第五章 继承与派生,第六章 多态性与虚函数,第七章 输入输出流,结束放映,第一章,C+,的初步知识,1.1,从,C,到,C+,1.2 C+,语言的词法和词法规则,1.3,最简单的,C+,程序,1.4 C+,对,C,的扩充,1.5 C+,程序的编写和实现,1.1,从,C,到,C+,C,语言是结构化和模块化的语言,,C,程序的设计者必须细致地设计程序中的每个细节,准确地考虑程序运行时每一时刻发生的事情,当程序规模变大时,结构化程序设计就显得力不从心。,为了解决软件设计危机,在,20,世纪,80,年代提出了面向对象的程序设计思想(,OOP,)在实践中人们发现,C,语言使用如此广泛,如果在它的基础上发展一种面向对象的语言,一定会让大众容易接收这种语言,所以产生了,C+,。,AT&T,发布的第一个,C+,编译系统是一个预编译器,它把,C+,代码转换成,C,代码,然后再用,C,编译系统生成目标代码。,1988,产生第一个,C+,编译系统,1989 C+2.0,类的多重继承,1991 C+3.0,类的模板,C+4.0,异常处理、命名空间,1997 ANSI,发布,C+,标准,C+,既可以用于面向过程的结构化程序设计,也可用于面向对象的程序设计。,C+,对,C,的增强体现在两个方面:,1.,对原来的面向过程机制做了扩充。,2.,增加了面向对象的机制。,学习,C+,之后,既可以进行面向对象的程序设计,也可以进行面向过程的程序设计。,1.2,C+,语言的词法和词法规则,C+,语言的字符集,等同于,C,语言的字符集,包括:(,1,)大小写英文字母(,2,)数字字符(,3,)其他,ASCII,码字符(,除,、,$,外,)。,单词及词法规则,单词是构成语句的关键成份之一,通常由若干字符组成,,C+,有几种单词:,1.,关键字,2.,标识符,3.,运算符,4.,分隔符,5.,注释符。,关键字,是,C+,语言中的命令字,它是预定义好的单词,,C+,编译程序对其有专门的解释。,int,、,float,、,if,、,else,、,while,、,switch,等等。,标识符,程序员用标识符对程序中元素实施命名,包括函数名、类名、对象名、类型名、变量名、常变量名、数组名等。,标识符以字母或下划线开始,后跟字母、数字、下划线,,标识符区分大小写字母,。,运算符,运算符代表某种操作的单词,由一个或多个字符组成。,注意运算符的优先级和结合顺序。参考本书附录,B,(,P287,)。,分隔符,在语句中关键字和标识符之间、各个语句之间要用分隔符分开。,C+,常用的分隔符有空格、逗号、分号、冒号、大括号。,注释符,C+,提供了两种注释符。,/*,注释*,/,/,注释,1.3,最简单的,C+,程序,例,1.1,输出一行字符“,This is a C+program.”,。,#include,/,用,cout,输出时需要用,/,此头文件,using namespace std;,/,使用命名空间,std,int main(),coutThis is a C+program.n;,/,上面用,C+,的方法输出一行,return 0;,(1),标准,C+,规定,main,函数必须声明为,int,类型,如果程序正常运行,向操作系统返回一个零值,否则返回非零值,通常是,-1,。,(2)C+,程序中可以用,/*/,做注释,可以用,/,做注释。前者可以做多行注释,后者只做单行注释。,(3)C+,程序中常用,cout,、,cin,进行输出输入,,cout,是,C+,定义的输出流对象,,ab;/,输入语句,sum=a+b;/,赋值语句,couta+b=sum”,是提取运算符,与,cin,配合,其作用是从输入设备中提取数据送到输入流,cin,中。在程序执行时,键盘输入的第一个数据赋予,a,,第二个数据赋予,b,。,cout,语句中的,endl,是,C+,控制符常数,作用是让光标换行。,如果在本程序运行时输入:,123 456 ,程序则输出:,a+b=579,例,1.3,求两个数中的大数,#include,using namespace std;,int main(),int max(int x,int y),;,/,对,max,函数作声明,int a,b,c;,cinab;,c=max(a,b);/,调用,max,函数,coutmax=cy)z=x;,else z=y;,return(z);,本程序包含两个函数,主函数,main,和被调用的函数,max,。,max,函数的作用是将两个整数中的大数赋予变量,z,。,return,语句将,z,的值返回给主函数,main,。返回值是通过函数名,max,带回到,main,函数的调用处。,程序运行情况如下:,18 25 (,输入,18,和,25),max=25 (,输出最大值,25),第二讲,例,1.4,包含类的,C+,程序,#include,using namespace std;,class Student /,声明一个类,类名为,Student,private:/,以下为类中的私有部分,int num;/,私有变量,num,int score;/,私有变量,score,public:/,以下为类中公用部分,void setdata()/,定义公用函数,setdata,cinnum;/,输入,num,的值,cinscore;/,输入,score,的值,void display()/,定义公用函数,display,coutnum=numendl;/,输出,num,的值,coutscore=scoreendl;/,输出,score,的值,;/,类的声明结束,Student stud1,stud2;,/,定义,stud1,和,stud2,为,Student,类的变量,称为对象,int main()/,主函数首部,stud1.setdata();/,调用对象,stud1,的,setdata,函数,stud2.setdata();/,调用对象,stud2,的,setdata,函数,stud1.display();/,调用对象,stud1,的,display,函数,stud2.display();/,调用对象,stud1,的,display,函数,return 0;,程序中声明一个被称为类的类型,Student,。声明时要用关键字,class,。,C+,类中可以包含两种成员即数据,(,如变量,num,、,score),和函数,(,如,setdata,函数和,display,函数,),。分别称为数据成员和成员函数。,在,C+,中将一组数据和访问这组数据的函数封装在一起,组成类。一个类是由一组数据,一组对其访问的若干函数,以及数据和函数的访问属性组成的。在前面程序中看到的,private,(私有),public,(公有)保留字代表数据和函数的访问属性。,凡是指定为公有的数据和函数,既可由本类的函数访问和调用,也可由其他函数或语句访问和调用;凡是指定为私有的数据和函数,通常只能由本类的函数访问和调用。,程序中“,Student stud1,stud2;”,是一个定义语句,定义两个,Student,类型变量,stud1,和,stud2,,,Student,类与,int,一样是,C+,的合法类型。,具有类类型的变量称为对象。,Student,的对象,stud1,,,stud2,具有同样的结构和特征。,在类外调用成员函数时必须在函数名前冠以类的名称。,主函数中第一条语句输入学生,1,的学号和成绩,第二条语句输入学生,2,的学号和成绩,第三条语句输出学生,1,的学号和成绩,第四条语句输出学生,2,的学号和成绩。程序运行情况如下:,1001 98.5 ,1002 76.5 ,num=1001,Score=98.5,num=1002,Score=76.5,为了与,C,兼容,,C+,保留了,C,语言中的一些规定,例如头文件的文件名,以,C,语言里头文件的扩展名是,.h,,许多,C+,编译系统保留了这种扩展名,近年推出的,C+,编译系统新版本,推出了一批不带扩展名的头文件如,iostream,,,string,,,cmath,等。为了兼容,C+,仍允许使用带扩展名的头文件。由于,C,语言无命名空间,因此使用带扩展名的头文件时不用,using namespace std,。,1.3 C+,对,C,的扩充,C+,既可用于面向过程的程序设计,也可用于面向对象程序设计。,C+,继承了,C,语言提供的绝大部分功能和语法规定,并在此基础上作了扩充。,1.4.1 C+,的输入和输出,1.4.2,用,const,定义常变量,1.4.3,函数原型声明,1.4.4,函数的重载,1.4.5,函数模板,1.4.6,有默认参数的函数,1.4.7,变量的引用,1.4.8,内置函数,1.4.9,作用域运算符,1.4.10,字符串变量,1.4.11,动态分配,/,回收内存运算符,1.3.1 C+,的输入输出,C+,为了方便使用,除了可以利用,printf,和,scanf,函数进行输入和输出外,还增加了标准输入流输出流,cin,和,cout,。它们是在头文件,iostream,中定义的,标准流是不需要打开文件和关闭文件就能直接操作的流式文件,在此标准输入流是指从键盘上输入的数据,标准输出流是指向屏幕输出的数据流。,C+,预定义的标准流如表,1.2,所示。,1.,用,cout,进行输出,格式:,cout,表达式,1,表达式,2,功能:由左向右逐个计算表达式的值,将其插入到输出流,cout,中。,cout,必须与输出运算符,一起使用,每个,后跟一个表达式,,运算符的结合方向是从左向右,所以各个表达式的值按从左到右的顺序插入到输出流中。,For (k=1;k =3;k+),cout“k=“kendl,endl,是,C+,输出流的常数,在头文件,iostream,中定义,代表让光标换行。在,C+,中也可以用”,n”,控制光标换行。所以输出语句也可写成:,cout“k=“k,变量,1,变量,2,是,C+,的提取运算符,表示从标准输入设备取得数据,赋予其后的变量。,从键盘输入数值数据时,两个数据之间用空格分隔或用回车分隔。,int a;float b,cinab;,从键盘输入,20 32.45 ,例,1.5 cin,和,cout,的使用,#include,using namespace std;,int main(),coutplease enter your name and age:name;,cinage;,coutyour name is nameendl;,coutyour age is agea)a=b;,if(ca)a=c;,return a;,float max(float a,float b,float c),/,求,3,个实数中的最大者,if(ba)a=b;,if(ca)a=c;,return a;,long max(long a,long b,long c),/,求,3,个长整数中的最大者,if(ba)a=b;,if(ca)a=c;,return a;,int main(),int a,b,c;float d,e,f;long g,h,i;,cinabc;,cindef;,cinghi;,int m;,m=max(a,b,c);,/,函数值为整型,cout max_i=mendl;,float n;,n=max(d,e,f);,/,函数值为实型,coutmax_f=nendl;,long int p;,p=max(g,h,i);,/,函数值为长整型,coutmax_l=pa)a=b;,if(ca)a=c;,return a;,int max(int a,int b),/,求两个整数中的最大者,if(ab)return a;,else return b;,int main(),int a=7,b=-4,c=9;,coutmax(a,b,c)endl;,/,输出,3,个整数中的最大者,coutmax(a,b)a)a=b;,if(ca)a=c;,return a;,int main(),int i1=8,i2=5,i3=6,i;,double d1=56.9,d2=90.765,d3=43.1,d;,long g1=67843,g2=-456,g3=78123,g;,i=max(i1,i2,i3);,d=max(d1,d2,d3);,g=max(g1,g2,g3);,couti_max=iendl;,coutd_max=dendl;,coutg_max=gendl;,return 0;,从程序中看到,此问题用函数模板比用函数重载更方便。注意,函数模板只适用于函数参数的个数相同而类型不同,并且函数体相同的情况,如果函数的参数个数不同,则不能用函数模板。,1.4.6,有默认参数的函数,C+,允许为函数的参数设置默认值,这时调用函数时,如果没有实参,就以默认值作为实参值。,格式:,形参类型 形参变量名,=,常数,功能:调用函数时,如果没有实参,就以常数作为该形参的值,;,如果有实参,仍以实参的值作为该形参的值。,注意:有默认值的形参必须放在形参表的右边,不允许无默认参数值和有默认参数值的形参交错排列。,例:编写计算圆柱体体积函数,float volume(float h,float r=12.5,),调用可以采用以下任何一种形式:,volume(45.6);,volume(32.5,10.5);,函数参数结合从左到右,用第一种方式调用时,只有一个实参,圆半径的值取默认值,12.5,,用第二种方式调用时,有两个实参,圆半径的值取实参的值,10.5,。,注意:,一、如果用函数原型声明,只要在函数原型声明中定义形参的默认值即可。,二、一个函数名不能同时用于重载函数和带默认形参值的函数。当调用函数时,如少写一个参数,系统无法判断是利用重载函数还是利用带默认参数值的函数,出现二义性。,例如将,例,1.7,中的第三行改为,int max(int a,int b,int c=100);,此时,max,是重载函数,又带默认参数值,如果出现,max(5,23),形式的调用,编译系统无法断定调用哪个函数,于是发出编译出错的信息。,1.4.7,变量的引用,C+,提供了为变量取别名的功能,这就是变量的引用。,格式:类型,&,变量,1=,变量,2,变量,2,是在此之前已经定义过的变量,且与变量,1,的类型相同。这里为变量,2,定义一个别名变量,1,,在程序里变量,1,和变量,2,就是同一个变量。,注意:两个变量不能用同一个别名。,例:,int a=3,b=4;,int,/c,是,a,的别名,int,/,错误的用法,一个变量可以有多个别名,例:,int a=3;,int,int,变量,a,有两个别名,b,和,c,。,#include,using namespace std;,int main(),int a=10;,int,/,声明,b,是,a,的引用,a=a*a;,/a,的值变化了,,b,的值也应一起变化,couta bendl;,b=b/5;,/b,的值变化了,,a,的值也应一起变化,coutb aendl;,return 0;,图,1.1,程序运行结果如下:,100,20,20,将引用作为函数参数,C+,除了可以用普通变量、指针变量做形参外,还可以用引用变量做形参。,(,1,)用普通变量做形参,这时传递的是实参的值,在函数内形参与实参是两个不同的内存单元,对形参的修改不会影响实参的值。,例,1.10,无法实现两个变量的值互换的程序,#include,using namespace std;,void swap(int a,int b),int temp;,temp=a;,a=b;,b=temp;,/,实现,a,和,b,的值互换,int main(),int i=3,j=5;,swap(i,j);,couti,jendl;,/i,和,j,的值未互换,return 0;,图,1.2,(,2,)用指针变量做形参,C,语言还允许用指针变量做形参,这时传递的是实参变量的地址(指针),在函数内利用这个指针访问实参变量。,例,1.11,用指针变量做形参,实现两个变量值的交换。,#include,using namespace std;,void swap(int*p1,int*p2),int temp;,temp=*p1;,*p1=*p2;,*p2=temp;,int main(),int i=3,j=5;,swap(,couti,jendl;,return 0;,图,1.3,(,3,)用引用变量做形参,用指针变量做形参,它将实参变量的地址传递给形参,在函数内用“*指针变量”的方式访问实参变量。我们知道引用变量是变量的别名,在调用函数时,用引用变量做的形参就成了实参变量的别名,在函数中用的形参名就是实参的别名,这样比用指针变量更直观、更方便。,例,1.12,利用引用变量实现两个变量值的交换,#include,using namespace std;,void swap(int&a,int&b),int temp;,temp=a;,a=b;,b=temp;,int main(),int i=3,j=5;,swap(i,j);,couti=i j=ja)a=b;,if(ca)a=c;,return a;,int main(),int i=7,j=10,k=25,m;,m=max(i,j,k);,coutmax=ma)a=b;,if(ca)a=c;,m=a;,例,1.15,用内置函数计算平方根,#include,using namespace std;,inline int power(int x),/,定义内置函数,return x*x;,int main(),coutpower(2)endl;,coutpower(1+1)endl;,return 0;,编译程序遇见内置函数,power,时,先求出函数的实参值(,1+1=2,),然后用,power,函数体代替函数调用,调用语句变成:,cout2*2endl;,cout2*2endl;,运行结果是,4,4,使用内置函数可以节省程序的运行时间,但增加了目标程序的长度。所以在使用时要衡量时间和空间的得失。,1.4.9,作用域运算符,并不是所有的变量在程序运行的时时刻刻都是可见的。有的变量在整个程序运行期间都是可见的,称它们为全局变量;有的变量只能在一个函数中可知,被称为局部变量。,每个变量都有其有效的,作用域,,程序只能在变量的有效的作用域内使用变量,不能直接使用其他域中的变量。,程序的内存区域,程序的内存空间,代码区,全局数据区,堆区,栈区,程序中各个函数的代码,程序中全局数据和静态数据,程序中的动态数据,程序中各函数内的数据,例,1.16,局部变量和全局变量同名,#include,using namespace std;,float,a=13.5,;,int main(),int,a=5,;,coutaendl;,return 0;,程序中有两个变量,a,,一个是全局变量,另一个是,main,函数的局部变量,根据局部变量会屏蔽同名的全局变量规则,在函数中出现的变量,a,是局部变量,因此输出的值是,5,,而不是,13.5,,,为了在函数中访问全局变量,C+,提供了,作用域,运算符,:,,可以用来指定要访问的作用域,可以把,main,函数改写成,#include,using namespace std;,float a=13.5;,int main(),int a=5;,coutaendl;,cout,:,a,字符串变量,cout,、,=,、,=,、,!=,、,、,“chinese”,运算结果是假。,1.4.11,动态分配,/,撤销内存的运算符,new,和,delete,分配内存运算,new,类型,(初值),类型是决定分配空间尺寸的关键元素,如果运算结果正确,它的值是分配内存空间的起始地址,否则返回,NULL,。,例:,int *a=new int;,int *b=new int(100);,char*ch=new char10;,int*q=new int 54;,float *p=new float(3.14159);,归还动态内存运算,delete,指针变量,代表数组,如果不是数组可以省略,。,运算功能:撤销指针变量所指的动态内存空间,指针变量的数据类型决定了空间尺寸的大小。,例:,char*p=new char10;,delete p;,例,1.18,用动态内存存放结构体变量,#include,#include,using namespace std;,struct student,char name 10;,int num;,char sex;,;,int main(),student*p;,p=new student;,strcpy(p-name,Wang Fun);,p-num=10123;,p-sex=M;,coutnamenumsex num;,cin name;,cin sex;,void display(),cout numendl;,cout nameendl;,cout sex num;,cin name;,cin sex;,void display(),cout numendl;,cout nameendl;,cout sex num;,cin name;,cin sex;,void,student:,display(),cout numendl;,cout nameendl;,cout sex num;,cin name;,cin sex;,void,student:,display(),cout numendl;,cout nameendl;,cout sex hour minute sec;,;,可以用下面的语句计算该类对象占用的字节数,cout sizeof(Time)endl;,结果输出值是,12,,这是数据成员所占的空间尺寸,这就证明一个对象占用的空间其实是它的数据成员占据的内存空间。,2.4,对象成员的引用,定义了对象后,在程序中可以直接访问对象中的公有成员,它们可以是数据成员,也可以是成员函数。,在程序中访问对象成员有三种方法。,2.4.1,用对象名和成员运算符访问成员,2.4.2,用指向对象的指针访问成员,2.4.3,用对象的引用访问成员,2.4.1,通过对象名和成员运算符访问对象中的成员,格式:对象名,.,成员名,例:,st1.display();,/,调用成员函数,display();,/,调用普通函数,注意:只有成员函数可以访问类中的所有成员,而在类外只能访问公有成员。,如果在类外面用下面的语句是错误的:,st1.num=10101,2.4.2,通过指向对象的指针访问对象中的成员,可以通过指针访问对象中的成员。,class Time,public:,int hour;,int minute;,;,Time t,*p;,p=,couthourhour,表示,p,当前指向对象,t,中的成员,hour,此时,(*p).hour,也代表对象,t,中的成员,hour,,在这个例子中,,p-hour,、,(*p).hour,、,t.hour,三种表示是一个意思。,2.4.3,通过对象的引用来访问对象中的成员,如果为一个对象,A,定义一个引用,B,,,B,是对象,A,的别名,,A,和,B,都是一个对象,所以完全可以通过引用访问对象中的成员。,Time t1;,Time,coutt2.hour;,cint2.minute;,cint1.sec;,coutt1.hour:t1.minute:t2.sect1.hour t1.minutet1.sec;coutt1.hour:t1.minute:t1.sec,coutt2.hourt2.minutet2.sec;coutt2.hour:t2.minute:t2.sec,coutt.hour;,cint.minute;,cint.sec;,void show_time(Time&t),coutt.hour:t.minute:t.sechour;,cinminute;,cinsec;,void Time:show_time(),couthour:minute:secendl;,例,2.4,在整型数组中找最大值,#include,using namespace std;,class Array_max,public:,void set_value();,void max_value();,void show_value();,private:,int array10;,int max;,;,void Array_max:set_value(),int i;,for(i=0;iarrayi;,void Array_max:max_value(),int i;,max=array0;,for(i=1;imax)max=arrayi;,void Array_max:show_value(),coutmax=num name;,cin,age,sex;,void,student:,display(),cout numendl nameendl;,cout,age,endl sex num;,cin name;,cin sex;,void,student,:,display(),cout num endl;,cout name endl;,cout sex t.hour;,cint.minute;,cint.sec;,int show_time(void),coutt.hour:t.minute:t.sechour;,cinminute;,cinsec;,void Time:show_time(),couthour:minute:secendl;,在类,Time,中定义了构造函数,Time,,它与所在的类同名。在建立对象时自动执行构造函数,该函数的作用是为对象中的各个数据成员赋初值,0,。注意只有执行构造函数时才为数据成员赋初值。,程序运行时首先建立对象,t1,,并对,t1,中的数据成员赋初值,0,,然后执行,t1.set_time,函数,从键盘输入新值给对象,t1,的数据成员,再输出,t1,的数据成员的值。接着建立对象,t2,,同时对,t2,中的数据成员赋初值,0,,最后输出,t2,的数据成员的初值。,程序运行的情况为:,10 25 54,10,:,25,:,54,/,输出,t1,的值,0,:,0,:,0,/,输出,t2,的值,也可以在类内声明构造函数然后在类外定义构造函数。将程序修改为:,Time();,然后在类外定义构造函数:,Time:Time(),hour=0;,minute=0;,sec=0;,关于构造函数的使用,说明如下:,(,1,)什么时候调用构造函数呢?当函数执行到对象定义语句时建立对象,此时就要调用构造函数,对象就有了自己的作用域,对象的生命周期开始了。,(,2,)构造函数没有返回值,因此不需要在定义中声明类型。,(,3,)构造函数不需要显式地调用,构造函数是在建立对象时由系统自动执行的,且只执行一次。构造函数一般定义为,public,。,(,4,)在构造函数中除了可以对数据成员赋初值,还可以使用其他语句。,(,5,)如果用户没有定义构造函数,,C+,系统会自动生成一个构造函数,而这个函数体是空的,不执行初始化操作。,3.1.3,带形参数的构造函数,可以采用带参数的构造函数,在调用不同对象的构造函数时,从外边将不同的数据传递给构造函数,实现不同对象的初始化。构造函数的首部的一般格式为:,构造函数名,(,类型 形参,1,,类型 形参,2,,,),在定义对象时指定实参,定义对象的格式为:,类名 对象名,(,实参,1,,实参,2,,,);,例,3.2,有两个长方柱,其长、宽、高分别为:,(,1,),12,,,25,,,30,(,2,),15,,,30,,,21,编写程序,在类中用带参数的构造函数,计算它们的体积。,分析:可以在类中定义一个计算长方体体积的成员函数计算对象的体积。,#include,using namespace std;,class Box,public:,Box(int,int,int);,int volume();,private:,int height;,int width;,int length;,;,Box:Box(int h,int w,int len),/,长方体构造函数,height=h;,width=w;,length=len;,int Box:volume(),/,计算长方体的体积,return(height*width*length);,int main(),Box box1(12,25,30);,/,定义对象,box1,cout box1,体积,=box1.volume()endl;,Box box2(15,30,21);,/,定义对象,box2,cout box2,体积,=box2.volume()endl;,return 0;,构造函数,Box,有,3,个参数,分别代表长、宽、高。在主函数中定义对象,box1,时,指定了实参,12,,,25,,,30,。然后调用成员函数计算长方体的体积。,程序运行的结果如下:,box1,体积,=9000,box2,体积,=9450,提醒:,(1),带形参的构造函数在定义对象时必须指定实参,(2),用这种方法可以实现不同对象的初始化。,3.1.4,用参数初始化表对数据成员初始化,C+,提供了参数初始化表的方法对数据成员初始化。这种方法不必在构造函数内对数据成员初始化,在函数的首部就能实现数据成员初始化。,函数名,(,类型,1,形参,1,,类型,2,形参,2),:,成员名,1(,形参,1),成员名,2(,形参,2),功能:执行构造函数时,将形参,1,的值赋予成员,1,,将形参,2,的值赋予成员,2,,形参的值由定义对象时的实参值决定。,此时定义对象的格式依然是带实参的形式:,类名 对象名,(,实参,1,,实参,2),;,例:定义带形参初始化表的构造函数,Box:Box(int h,int w,int len),:,height(h),width(w),length(len),定义对象:,Box box1(12,25,30);,Box box2(15,30,21);,3.1.5,构造函数的重载,构造函数也可以重载。一个类可以有多个同名构造函数,函数参数的个数、参数的类型各不相同。,例,3.3,:在例,3.2,的基础上定义两个构造函数其中一个无参数,另一个有参数。,#include,using namespace std;,class Box,public:,Box();,Box(int h,int w,int len):height(h),width(w),length(len),int volume();,private:,int height;,int width;,int length;,;,Box:Box(),height=10;,width=10;,length=10;,int Box:volume(),return(height*width*length);,int main(),Box box1;,coutbox1,体积,=box1.volume()endl;,Box box2(15,30,25);,coutbox2,体积,=box2.volume()endl;,return 0;,例子中定义了两个构造函数,一个无参数另一个带三个参数。系统根据定义对象的格式决定调用哪个构造函数。对象,box1,没有实参系统为它调用无参数的构造函数;对象,box2,带三个实参系统为它调用带形参的构造函数。,说明:,(,1,)不带形参的构造函数为默认构造函数每个类只有一个默认构造函数,如果是系统自动给的默认构造函数,其函数体是空的。,(,2,)虽然每个类可以包含多个构造函数,但是创建对象时,系统仅执行其中一个。,3.1.6,使用默认参数值的构造函数,C+,允许在构造函数里为形参指定默认值,如果创建对象时,未给出相应的实参时,系统将用形参的默认值为形参赋值。,格式:,函数名,(,类型 形参,1=,常数,类型 形参,2=,常数,,);,例,3.4,:将例,3.3,中的构造函数改用带默认值的参数,长、宽、高的默认值都是,10,。,#include,using namespace std;,class Box,public:,Box(int w=10,int h=10,int len=10);,int volume();,private:,int height;,int width;,int length;,;,Box:Box(int w,int h,int len),height=h;,width=w;,length=len;,int Box:volume(),return(height*width*length);,int main(),Box box1;,coutbox1,体积,=box1.volume()endl;,Box box2(15);,coutbox2,体积,box2.volume()endl;,Box box3(15,30);,coutbox3,体积,box3.volume()endl;,Box box4(15,30,20);,coutbox4,体积,box4.volume()endl;,return 0;,程序运行结果为:,box1,体积,=1000,box2,体积,=1500,box3,体积,=4500,box4,体积,=9000,构造函数也可以改写成带参数初始化表的形式:,Box:Box(int h,int w,int len),:,height(h),width(w),length(len),整个函数只需一行,简单方便。,在构造函数中使用默认参数提供了建立对象的多种选择,它的作用相当于多个重载构造函数。,说明:,(,1,)如果在类外定义构造函数,应该在声明构造函数时指定默认参数值,在定义函数时可以不再指定默认参数值。,(,2,)在声明构造函数时,形参名可以省略例如:,Box(int=10,int=10,int=10);,(,3,)如果构造函数的所有形参都指定了默认值,在定义对象时,可以指定实参也可不指定实参。由于不指定实参也可以调用构造函数,因此全部形参都指定了默认值的构造函数也属于默认构造函数。为了避免歧义,不允许同时定义不带形参的构造函数和全部形参都指定默认值的构造函数。,(,4,)同样为了避免歧义性,如定义了全部形参带默认值的构造函数后,不能再定义重载构造函数。反之亦然。,Box(int=10,int=10,int=10);,Box();,Box(int,int);,若定义对象:,Box box1;,Box box2(15,30);,这时应该调用哪个构造函数呢?如果构造函数中参数并非都带默认值时,要具体分析情况。如有以下三个原型声明:,Box();,Box(int,int=10,int=10);,Box(int,int);,若定义对象:,Box box1;,/,正确,调用第一个,Box box2(15);,/,调用第二个,Box box3(15,30);,/,不知调用哪一个,因此不要同时使用重载构造函数和带默认值的构造函数。,3.2,析构函数,析构函数也是个特殊的成员函数,它的作用与构造函数相反,当对象的生命周期结束时,系统自动调用析构函数,收回对象占用的内存空间。,执行析构函数的时机:,在一个函数内定义的对象当这个函数结束时,自动执行析构函数释放对象。,static,局部对象要到,main,函数结束或执行,exit,命令时才
展开阅读全文