C∕C++程序设计教程(下)ppt.ppt_第1页
C∕C++程序设计教程(下)ppt.ppt_第2页
C∕C++程序设计教程(下)ppt.ppt_第3页
C∕C++程序设计教程(下)ppt.ppt_第4页
C∕C++程序设计教程(下)ppt.ppt_第5页
已阅读5页,还剩144页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

,CC+程序设计教程(下),第14章 C+面向对象程序设计,C+面向对象程序设计,C语言具有许多优点,但是随着社会对软件需求的不断扩大、复杂性不断提高、规模日益增加,结构化的方法,就很难适应这种变化的需要。为了适应这种变化的需要,一种新的程序设计方法面向对象的程序设计方法被提出,当然面向过程的程序设计语言就不能满足这种新方法的需要。在20世纪80年代,在C语言基础上,增加了对面向对象程序设计方法的支持,形成带类的C,1983年正式命名为C+。,C+面向对象程序设计,在本章介绍的内容有: C+语言的特点 由C向C+过渡 面向对象的方法 类与对象 继承与派生 多态性,14.1 C+的特点,特点: 对C兼容、支持面向对象,但不是纯真面向对象的语言,支持面向过程的结构化程序设计,又支持面向对象的程序设计 不是高级的C,从概念上讲,是完全不同的计算机语言。,14.2由C向C+过渡,与类无关的C+语言的独特之处 1、注释行 在C+中,除了用“/*”和“*/”括起来作为注释分界符号外,另一种更有效的注释方法就是使用“/”,从“/”开始直到它所在行的行尾,所有字符均被作为注释处理。如: /This is a example. int i;/i is a integer2).,14.2由C向C+过渡,2、声明语句 在C+中,可以在任何需要的地方声明变量,但是我们不提倡这样,它不利于程序的维护。如: for(int i=0;i10;i+) int length=5*i; ,14.2由C向C+过渡,3、C+的输入输出 1. I/O流 在C中,printf和scanf是两个标准输入输出函数,在头文件stdio.h中声明。在C+面向对象程序设计中,将数据从一个对象到另一个对象的流动抽象为“流”。从流中获取的操作称为提取操作,向流中添加数据的操作称为插入操作。C+的输入输出是通过I/O流来实现的,cin和cout是预定义的流类对象,它们是在iostream.h中定义的。cin用来处理标准输入,即键盘输入。cout用来处理标准输出,即显示器输出。C+预定义的标准流如表14.1,14.2由C向C+过渡,3、C+的输入输出 1. I/O流 流名 含义 默认设备cin 标准输入 键盘cout 标准输出 显示器cerr 标准出错输出 显示器clog cerr的缓冲形式 显示器,14.2由C向C+过渡,3、C+的输入输出 2. 预定义的插入符和提取符 当程序需要在屏幕上显示输出时,可以使用插入操作符“”向cout输出流中插入字符,格式如下: cout表达式1表达式2 例: cout “This is a program.n”; cout”a+b=”a+b; 在输出语句中可以串联多个插入运算符,输出多个数据。在插入运算符后可以加任意复杂的表达式。,14.2由C向C+过渡,3、C+的输入输出 2. 预定义的插入符和提取符 当程序需要执行键盘输入时,可以使用抽取操作符“”,从键盘取得数据送到输入流cin中,再到内存。格式如下: cin表达式1表达式2 例: int a,b; cinab; 在输入语句中,提取操作符可以连续多个,每一个后面跟一个表达式,该表达式一定是用来存放输入数据的变量。 下面举一个完整的例:,14.2由C向C+过渡,3、C+的输入输出 2. 预定义的插入符和提取符 【例141】 从键盘输入两个数,找出最大值,显示最大值的平方根。 #include #include void main() double a,b,c; cout a b;/处理键盘输入,即从cin流中取数据 c = ab?a:b; cout “the squart of maximum = “ sqrt(c) endl;/显示c的平方根 ,14.2由C向C+过渡,4、关于自定义数据类型变量的定义 同C中一样,可以采用3种方式定义结构体变量,但是在C+中,有一个例外,就是在先声明结构体,后定义变量时,不像在C语言中,结构体变量定义时,结构类型名前必须有struct关键字,而C+中,不需要struct前缀。 例 struct student int num; char name20; char sex; int age; ; 定义变量: student stu1,stu2;,14.2由C向C+过渡,4、关于自定义数据类型变量的定义 除结构体外,还有公用体、枚举类型,在先声明后定义变量时,也不需要加前缀enum、union。 由于有这样的特点,因此在同一个作用范围内,结构体、公用体和枚举类型的名不能与用typedef定义的类型同名,但在C中是允许的。 例: typedef int typeA; struct typeA ; 这种形式在C中是合法的,但在C+中就造成了错误。,14.2由C向C+过渡,5、任何函数调用之前必须有函数声明或定义 在C语言中允许在调用函数前不声明或定义函数,例如: 【例142】 调用函数,输出两个数中的最大值 main() int x=5,y=4,m; m=max(x,y); printf(“%dn”,m); 但在C+中是非法的,C+中所有函数在调用前必须声明或定义。,max(int x,in y) return xy?x:y; ,14.2由C向C+过渡,5、任何函数调用之前必须有函数声明或定义 在C语言中允许在调用函数前不声明或定义函数,例如: 【例143】 调用函数,输出两个数中的最大值 #include int max(int x,in y) return xy?x:y; void main() int x=5,y=4,m; m=max(x,y); coutmendl; ,14.2由C向C+过渡,6、函数声明时形式参数不能省略 C+中函数声明时,形式参数不能省略,并且只能采用ANSI新标准推荐的现代方式声明。如果省略,则所声明的函数就是无形式参数的函数。但在C中函数声明时,形式参数是可以省略的。,14.2由C向C+过渡,6、函数声明时形式参数不能省略 【例144】 调用函数,输出两个数中的最大值 #include int max(int,int); void main() int x=5,y=4,m; m=max(x,y); couty?x:y; ,14.2由C向C+过渡,6、内联函数 为了有利于代码重用和提高软件开发效率,增强程序的可读性、可靠性和可维护性,在程序中,一般都使用函数,但是,使用函数也会降低程序的执行效率。因为在函数调用时,需要保护现场和返回地址,然后去执行子函数。子函数执行完后,又要取出保存的地址和现场状态,再继续执行。这些都需要时间和资源。,14.2由C向C+过渡,6、内联函数 对于一些功能简单、程序规模小而又频繁使用的函数,可以设计为内联函数。内联函数与一般函数调用时不同,而是在编译时将函数体嵌入在每一个调用语句处,这样就节省了时间和资源。 内联函数在定义时使用关键字inline,格式有两种形式: 1)、声明同时定义函数体 inline 类型说明 函数名(含类型说明的形式参数) ;,14.2由C向C+过渡,2)、先声明后定义 声明形式如下: inline 类型说明 函数名(含类型说明的形式参数); 在程序的任何位置定义函数体,形式如下: 类型说明 函数名(含类型说明的形式参数) ; 在定义函数体时,不能再带有关键字inline。,14.2由C向C+过渡,注意:使用内联函数应注意以下两点: (1)、内联函数体内不能有循环语句和switch语句; (2)、内联函数必须在第一次调用前声明或定义。 对于复杂和规模大的函数,尽管使用频繁,也不要写成内联函数的形式,这样会增加程序的规模。例如:,14.2由C向C+过渡,【例145】内联函数的声明、定义与调用 #include inline int isnumber(char); /函数声明 void main() char c; while(c=cin.get()!=n)/接收输入 if(isnumber(c) /调用内联函数,并判定函数返回值 cout =0 ,14.2由C向C+过渡,14.2.8带默认形参值的函数 函数在定义时可以预先定义一个默认的形参值。在函数调用时,如果给出实参,则用实参初始化形参;如果没有给出实参,就用预先给定的默认值。 例如:,14.2由C向C+过渡,【例146】 带默认形参值的函数的声明与定义 #include int add(int a=5,int b=9)/形参a与b的默认值分别为5和9 return a+b;/两数相加 void main() add(15,20);/用实参初始化形参,实现15+20 add(15); /形参a用15,b用默认值9,返回值为24 add(); /a、b都用默认值,返回值为14 ,14.2由C向C+过渡,注意: 1)、如果定义某个形式参数带有默认值,则必须定义所有后续形式参数也带有默认值,即在有默认值参数的右面,不能出现无默认值的形参。例如: void ShowMessage(char *Text,int Length = -1,int Color); 此函数定义为错,应定义为: void ShowMessage(char *Text,int Length = -1,int Color = 0);,14.2由C向C+过渡,2)、调用函数时省略带有默认参数,则必须省略该参数所有后续参数 【例147】 #include void point(int x=5,int y=6,int z=7); /函数声明 void main() cout“显示默认参数:“endl; point(); /省略,14.2由C向C+过渡,所有参数利用默认值 cout“第二、三参数用默认值“endl; point(10); /省略第二、三参数利用默认值 cout“第三参数用默认值“endl; point(10,9); /省略第三参数利用默认值 cout“三个参数用实参传递的值“endl; point(10,9,8); /利用实参的值,14.2由C向C+过渡, void point(int x,int y,int z) /函数定义 cout“x=“xendl; /输出x cout“y=“yendl; /输出y cout“z=“zendl; /输出z 运行结果为: 图14.1 程序运行结果,14.2由C向C+过渡,3)、如果是先声明后定义函数,则在声明时给出默认值,在定义时就不能给出默认值,否则出错。,14.2由C向C+过渡,14.2.9函数的重载 在C语言中,函数名不能相同,如果相同,就出错,但在C+中,提供了对重载的支持。所谓重载,就是在程序中相同的函数名对应不同的函数实现。函数重载允许程序内多个名称相同的函数,这些函数可以完成不同的功能,并且带有不同的类型、不同的形参个数及不同的返回值。,14.2由C向C+过渡,使用函数重载,就可以把功能相似的函数名命名为一个相同的标示符,减轻程序员对于函数的记忆负担,使程序结构简单、易懂。例如: 【例148】 求各种不同数据类型的和 #include ,14.2由C向C+过渡,/函数声明 int add(int,int); /两个整数相加 int add(int,int,int); /三个整数相加 double add(double,double); /两个浮点数相加 double add(double,double,double); /三个浮点数相加 void main() cout“求整数5、6的和“add(5,6)endl; cout“求整数5、6、7的和“add(5,6,7)endl; cout“求浮点数4.2、5.9的和“add(4.2,5.9)endl; cout“求浮点数4.2、5.9、9.3的和“add(4.2,5.9,9.3)endl; ,14.2由C向C+过渡,/函数定义 int add(int x,int y) /两个整数相加 return x+y; int add(int x,int y,int z) /三个整数相加 return x+y+z; double add(double x,double y) /两个浮点数相加 return x+y; double add(double x,double y,double z) /三个浮点数相加 return x+y+z; ,14.2由C向C+过渡,图14.2 程序运行结果,14.2由C向C+过渡,提示: 函数的重载要求编译器能够唯一地确定应该调用的函数,即应该采用哪一个函数来实现。为了不造成混乱,则要求重载函数的形参数个数或形参数的类型或形参的排列顺序不同。也就是说,函数重载,函数名可以相同,但函数形参的个数或类型或排列顺序不能相同。,14.2由C向C+过渡,14.2.10作用域操作符 作用域是一个标示符在程序中的作用范围。当局部变量与全局变量同名时,局部变量掩盖全局变量。但在有时需要操作与局部变量同名的全局变量时,就可以用作用域操作符“:”来访问全局变量,格式是在全局变量名前加作用域操作符。,14.2由C向C+过渡,例如: 【例149】 作用域操作符的使用 double A; /全局变量A void main( ) int A; / 局部变量A A = 5; / 为局部变量A赋值 :A = 2.5;/ 为全局变量A赋值 coutAendl;/输出局部变量的值5 cout:Aendl;/输出全局变量的值2.5 ,14.2由C向C+过渡,14.2.11 new和delete操作符 在编写程序时,常常需要动态分配和释放内存空间,在C语言中是利用库函数malloc()和free()函数来实现的。但是malloc函数需要预先知道应该分配的内存空间的大小,其调用形式为malloc(size),这里的size是分配的字节数。可以给定具体数,也可以用sizeof运算来测定。同时其返回值为void型,需要进行强制类型转化,才能得到所需要的指针指向的类型。,14.2由C向C+过渡,在C+中,提供了功能更强大的运算符new与delete,不需头文件,new比malloc( )更简练,new操作符自动确定对象的正确长度并返回正确类型指针。使用类对象时,new自动调用类的构造函数,delete自动调用类的析构函数。关于类对象、类构造函数、类析构函数在后面讲解。,14.2由C向C+过渡,例如: int *i;/定义一个指向整型的指针 i=new int;/分配一个存储整型数据的空间,返回一个指向整型数据的指针 i=new int(50); /分配一个存储整型数据的空间,返回一个指向整型数据的指针,并赋初值为50。 i=new int10; /分配一个长度为10的一维整型数组的空间,返回一个指向整型数组的指针,以后i就象int i10一样,来使用i。但是这里是动态分配的空间,当然在用完以后,可以撤消动态分配的空间,而int i10,所分配的空间是静态的。,14.2由C向C+过渡,用new分配空间的格式是: 1)、先定义指针变量,再分配存储空间 指针变量=new 类型(初值) 如:float *f; f=new float;/不给初值 或f=new float(3.14159);/给初值 再如:char *ch; ch=new char;/ 分配一个存储字符数据的空间,返回一个指向字符数据的指针。 或ch=new char50;/ 分配一个长度为10的一维字符数组的空间,返回一个指向字符数组的指针,14.2由C向C+过渡,2)、在定义指针变量的同时分配存储空间 例如:float *f=new float;/不给初值 或float *f=new float(3.14159);/给初值 再如:char *ch=new char;/ 分配一个存储字符 数据的空间,返回一个指向字符数据的指针。 或char *ch=new char50;/ 分配一个长度为10 的一维字符数组的空间,返回一个指向字符数组 的指针,14.2由C向C+过渡,用delete运算符释放用new分配的存储空间,其格式为: delete 被释放指针变量; 如:delete i; delete ch; 但是delete 释放的是数组时,应该在指针变量前带“”,以示要回收的是数组而不是单个基本类型对象。,14.2由C向C+过渡,例如: delete i;/ 释放的是数组 delete ch;/ 释放的是一个数组 例如: 【例1410】 new和delete运算符的使用 #include struct student /定义结构体 int num; /学号 char name20; /姓名 char sex; /性别 int age; /年龄 ;,14.2由C向C+过渡,void main() student *stu1; /定义一个指向结构体的指针 stu1=new student; /利用操作符为指针变量分配存储空间 stu1-num=20; /赋值 strcpy(stu1-name,”Xiao Qing”); /赋值 stu1-sex=F; /赋值 stu1-age=18; /赋值 delete stu1; /释放存储空间 ,14.2由C向C+过渡,先声明了一个结构体类型student,在主函数中定义了一个指向student类型的指针变量stu1,用new分配用于存储student类型数据的存储空间,空间的大小由系统根据student的自己确定,返回一个指向student类型的指针,存储在stu1中,然后就是给结构体的成员变量赋值。最后用delete运算符,释放被分配的存储空间。 提示:当用new分配存储空间失败时,返回的是一个空指针NULL,可以用来判断分配存储空间是否成功。 new与delete是运算符,成对使用,而malloc与free是一对函数,在C+中,保持了对这对函数的支持。,14.3 面向对象的方法,14.3.1 面向对象的语言 面向对象的程序设计语言与面向过程的程序设计语言的根本不同点在于:它设计的出发点不再是按照功能分解的方式来划分模块,而是以客观世界中存在的事物(即对象)为研究对象,研究对象的属性、行为以及对象之间相互作用的关系。 面向对象的程序设计语言经历了一个很长的发展过程,应用最广的面向对象的语言是由C语言发展而来的C+语言,由于它对C语言的兼容,而C语言已经被人们所熟悉,有C作为基础学习C+就有得天独厚的条件。,14.3 面向对象的方法,14.3.2 面向对象方法 面向对象方法的出发点,就是模拟人类的认识事物解决问题的过程来开发软件,这是学习和理解面向对象方法的关键。面向对象方法中提到的“对象”,是软件开发者根据自己的研究范畴来定义或选取。 对象通过抽象,找出同一类对象的共同属性和行为,形成类,如抽象汽车和火车的共同属性和行为,忽略其差异,形成“车”这个类。通过类的继承、多态就可以实现代码的重用,提高程序开发效率,缩短开发周期。,14.4 类与对象,在面向对象的程序设计中,程序的模块是由类构成的,类是数据和函数的封装体,是对所要处理的问题的抽象描述。类实际上相当于是用户自定义的数据类型,就象在C语言中的结构体一样,不同的是结构体中没有对数据的操作,类中封装了对数据的操作(在C+中结构体中也可以有对数据操作的函数,但与类的操作有区别),可以利用自定义的类型来定义变量,这个变量就称为类的对象(或实例),声明的过程称为类的实例化。,14.4 类与对象,14.4.1 类的定义 在使用类之前必须先定义类,定义一个类的语法格式为: class 类名 private: 私有成员数据和函数; protected: 保护成员数据和函数; public: 公有成员数据和函数; 类的对象定义;,14.4 类与对象,在面向对象的程序设计中,程序的模块是由类构成的,类是数据和函数的封装体,是对所要处理的问题的抽象描述。类实际上相当于是用户自定义的数据类型,就象在C语言中的结构体一样,不同的是结构体中没有对数据的操作,类中封装了对数据的操作(在C+中结构体中也可以有对数据操作的函数,但与类的操作有区别),可以利用自定义的类型来定义变量,这个变量就称为类的对象(或实例),声明的过程称为类的实例化。,14.4 类与对象,说明: 1)、class是关键字,不能省略; 2)、类名的命名规则,与C语言中的标示符的命名规则一致; 3)、类中的数据(又称数据成员)和函数(又称成员函数)分为三种访问控制属性,分别由三种访问控制修饰符 public(公有类型), private(私有类型), protected(保护类型)加以修饰。,14.4 类与对象,4)、private、protected和public是关键字,是对数据成员和成员函数的访问控制,不分先后顺序,用于修饰在它们之后列出的数据成员和成员函数能被程序的其它部分访问的权限。缺省的情况下为private。在声明类时,并不一定三种控制类型的成员必须都有。 5)、public: 指定其后的成员是公有的。它们是类与外部的接口,任何外部函数都可以通过对象访问公有数据成员和成员函数。 6)、private: 指定其后的成员是私有部分。若省略关键字private,则必须紧跟在类名称后声明。类中的数据和函数若不特别声明,都被视为私有类型。,14.4 类与对象,7)、protected:保护类型,这种类型的数据也只能被类本身的成员函数访问,但可以被派生类继承(关于派生类继承在后面介绍)。 【例1411】 类的定义与三种访问控制符的运用,14.4 类与对象,class Cperson /定义类、类名为Cperson public: /公有 void SetData(char name,int age,float height); private: /私有 char Name20; int Age; float Height; public: /公有 void PrintAge(); void PrintHeight(); ;,14.4 类与对象,1)、这里封装了人的数据和行为,分别称为CPerson类的数据成员和成员函数; 2)、各种访问控制在类的定义中,可以以任意的顺序出现,根据需要也可以同一种访问控制出现多次。,14.4 类与对象,14.4.2 类的成员函数 类的成员函数描述的是类的行为,它是程序算法的一部分,是对封装在类中的数据唯一的操作途径。 1.成员函数体的定义 函数的原型声明应该在类的主体中,原型声明时同C语言中函数的声明一样,而函数体的定义可以在类体中声明函数的同时定义函数体,也可以声明以后,在类体外,再来定义函数体。 1)、在类体中声明函数同时定义函数体 【例1412】 在定义类的同时定义函数,14.4 类与对象,class CPerson public: void SetData(char name,int age,float height)/给成员变量赋初值 strcpy(Name,name); Age=age; Height=height; Return; ; private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ;,14.4 类与对象,2)、在类体中声明函数,在类体外定义函数体 一般格式为: 返回值类型 类名:成员函数名(形参表) 函数体; 例如: 【例1413】 在类体中声明函数,在类体外定义函数体,14.4 类与对象,void Cperson:SetData(char name,int age,float height) strcpy(Name,name); Age=age; Height=height; return; ;,14.4 类与对象,2.带默认值的成员函数 在前面介绍了带默认形参值的函数。同样,在类中声明成员函数时,可以为成员函数的参数指定缺省参数值,但在定义函数体时,就不能再带有默认形参值,其声明、函数体的定义及调用规则同前面的讲的函数相同,在实际的程序设计中,默认值可以带来很大的方便。 例如: 【例1414】 带有默认参数值的成员函数声明与定义,14.4 类与对象,class CPerson public: void SetData(char name,int age=0,float height=0.0);/ 带默认形参值 private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ;,14.4 类与对象,/函数体的定义 void Cperson:SetData(char name,int age,float height) /不带默认形参值 strcpy(Name,name); Age=age; Height=height; return; ,14.4 类与对象,3.内联成员函数 类的成员函数也可以声明和定义成内联函数。内联函数是指定义在类体中的成员函数。内联函数在调用时不象一般的函数那样,转去执行被调用函数的函数体,而是编译时在调用函数处用内联函数的代码来替换。在C+中,可以使用两种格式来定义类的内联成员函数: 1)在定义类时,与一般成员函数的声明一样,但 在定义函 数体时,把关键字inline加在函数定义之前。,14.4 类与对象,【例1415】 带有内联函数的类的定义 class CPerson public: void SetData(char name,int age=0,float height=0.0);/ 带默认形参值 private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ;,14.4 类与对象,内联函数体的定义 inline void Cperson:SetData(char name,int age,float height) /在前面加关键字inline strcpy(Name,name); Age=age; Height=height; return; ,14.4 类与对象,2)、声明成员函数的同时定义函数体,这时的所定义的函数也是 内联函数。例如: 【例1416】 在类体中声明成员函数同时定义函数体 class CPerson public: void SetData(char name,int age,float height)/函数体位于类定义中 strcpy(Name,name); Age=age; Height=height; Return; ;,14.4 类与对象,private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ; 函数SetData()为内联函数。,14.4 类与对象,14.4.3构造函数和析构函数 在C+中,有两个特殊的函数,一个是构造函数(Constructor),一个是析构函数(Destructor),构造函数是用来进行初始化的,而析构函数是用来在最后清理工作的,如申请的内存释放等。这个函数不需要明显的调用,在对象使用完成后自动调用。,14.4 类与对象,1.构造函数 构造函数是一个特殊的成员函数,主要用来初始化,如:分配内存空间、赋初值。实际上如果我们不定义构造函数的话,默认的也有一个构造函数,只是这个构造函数不做任何初始化的工作,但构造函数是存在的。构造函数的函数名是类名,并且该函数没有返回值,也没有返回值的类型。可以有形式参数。 例如: 【例1417】 构造函数的声明形式,14.4 类与对象,class CPerson public: CPerson (char name,int age,float height);/构造函数 private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ;,14.4 类与对象,分析:构造函数体的定义与一般函数一样,可以在声明同时定义,也可以在声明后,再定义函数体,也可以有形式参数默认值。 先声明函数再定义函数体 【例1418】构造函数体的定义 Cperson:CPerson (char name,int age,float height) strcpy(Name,name); Age=age; Height=height; ;,14.4 类与对象,在类体中声明的同时定义函数体 例如: 【例1419】 在类体中声明的同时定义函数体 class CPerson public: CPerson (char name,int age,float height)/在类体中声明的同时定义函数体 strcpy(Name,name); Age=age; Height=height; ;,14.4 类与对象,private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ; 另外构造函数也可以重载。,14.4 类与对象,2.析构函数 析构函数也是一个特殊的成员函数,主要用来清理释放的工作,如:内存空间的释放。实际上如果我们不定义析构函数的话,默认的也有一个析构函数,只是这个析构函数不做任何事情,但析构函数是存在的。析构函数的函数名是类名,但要在函数名前加“”,并且该函数没有返回值,也没有返回值的类型,也没有形式参数。,14.4 类与对象,例如: 【例1420】 析构函数声明 class CPerson public: CPerson (char name,int age,float height) Name=new char20; strcpy(Name,name); Age=age; Height=height; ;,14.4 类与对象, Cperson();/析构函数 private: char *Name; int Age; float Height; public: void PrintAge(); void PrintHeight(); ;,14.4 类与对象,析构函数体的定义与一般函数一样,可以在声明同时定义,也可以在声明后,再定义函数。 (1)、先声明函数再定义函数体。例如: 【例1421】先声明析构函数再定义析构函数体 Cperson:CPerson () cout”这里删除Name”endl; delete Name; ;,14.4 类与对象,(2)、在类中声明析构函数的同时定义析构函数体。例如: 【例1422】 在类体中声明的同时定义析构函数体 class CPerson public: CPerson (char name,int age,float height) Name=new char20; strcpy(Name,name); Age=age; Height=height; ;,14.4 类与对象, Cperson()/在类体中声明的同时定义析构函数体 cout”这里删除Name”endl; delete Name; private: char Name20; int Age; float Height; public: void PrintAge(); void PrintHeight(); ; 另外析构函数不能被重载。,14.4 类与对象,14.4.4对象 在C+中,类是一种自定义的数据类型,对象是声明为类类型的一个实例(Instance),即为变量。因此对象的声明与声明一个基本类型的变量是一样的。 1.对象的定义 有两种方法可以定义类的对象:,14.4 类与对象,(1)、在定义类的同时直接定义类的对象,即: class 类名 成员变量; 成员函数: 对象名列表; 这里的对象名列表可以有一系列,但每个对象之间用逗号分开。 (2)、先定义类,再定义类的对象。即: 类名 类对象1,类对象2,;,14.4 类与对象,2.对象的公有成员的访问 只有类定义时,访问控制被定义为公有的成员才能被访问,这种访问采用的是对象选择符“.”,“.”点运算符,一般形式为: 对于成员函数的访问: 对象名.公有成员函数(实参); 对于成员变量的访问: 对象名.数据成员名=赋值;,14.4 类与对象,例如: 【例1423】 对象的定义与“.”点运算符的使用 #include #include const double ANG_TO_RAD=0.0174532925;/定义常数 class CAngle/定义类 double Value;/私有成员变量 public: void SetValue(double);/公有成员函数 double GetCos();/公有成员函数 vcos;/定义的同时定义类对象,14.4 类与对象,/成员函数定义 void CAngle:SetValue(double value)/为成员变量Value赋值 Value=value; double CAngle:GetCos()/计算cos值 double temp; temp=cos(ANG_TO_RAD*Value); return temp; ,14.4 类与对象,void main() vcos.SetValue(45.0);/给类成员变量Value赋值 cout“COS的值是:“; coutvcos.GetCos()endl;/输出值 CAngle vcos1;/定义另一个对象 vcos1.SetValue(60.0);/给类成员变量Value赋值 cout“COS的值是:“; coutvcos1.GetCos()endl;/输出值 ,14.4 类与对象,运行结果为: 图14. 程序运行结果 3.指向类对象的指针变量 (1)、定义 定义一个指向类对象的指针变量的方法,与定义指向基本类型的指针变量一样。格式为: 类名 *指针变量名;,14.4 类与对象,例如: CAngle *ang1; 应该说明的是:此时的指针并没有一个明确的指向,为了使其有一个明确的指向,应该用new操作符为它分配内存空间后,才能使用。一般格式为: 定义指针变量的同时分配内存空间: 类名 *指针变量名=new 类名; 例如: CAngle *ang1=new CAngle; 先定义指针变量,再分配内存空间:,14.4 类与对象,(2)、通过指向类对象的指针访问类的公有成员 通过指向操作符“-” 格式为: 指针变量名-数据成员; 指针变量名-成员函数; 如: ang1-SetValue(60.0);,14.4 类与对象,(3)、用delete操作符释放内存空间 当所定义的指针已经不再用时,应尽快释放其占有的内存空间。 一般格式为: delete 指针变量名; 例如: 【例1424】 指向类对象的指针访问类的公有成员 #include #include const double ANG_TO_RAD=0.0174532925;/定义常数,14.4 类与对象,class CAngle/定义类 double Value;/私有成员变量 public: void SetValue(double);/公有成员函数 double GetCos();/公有成员函数 *vcos;/定义的同时定义类对象指针 /成员函数定义 void CAngle:SetValue(double value) Value=value; double CAngle:GetCos() double temp; temp=cos(ANG_TO_RAD*Value); return temp; ,14.4 类与对象,void main() vcos=new CAngle;/分配内存空间 vcos-SetValue(45.0);/给类成员变量Value赋值 coutGetCos()SetValue(60.0);/给类成员变量Value赋值 cout“COS的值是:“; coutvcos1.GetCos()endl;/输出值 delete vcos1;/释放内存空间 ,14.4 类与对象,运行结果为: 图14.程序运行结果,14.5 继承与派生,类的继承,是新的类从已有的类那里得到已有的特性。换一个角度来说,从已有的类为基础产生新类的过程就是类的派生。原有的类称为基类,或称为父类。产生的新类称为派生类,或称为子类。派生类同样可以作为新的基类,产生新的派生类;新的派生类还可以作为基类,产生新的派生类,这样一直进行下去,就形成了类层次结构。类的派生实际是一个演化、发展过程,即通过扩展、修改和特殊化,从一个已知类出发建立新的类。通过类的派生可以建立具有共同关键特性的类群,从而实现了代码的重用。,14.5 继承与派生,14.5.1派生类的声明 在C+中,一个基类可以有一个或多个派生类。定义派生类的一般格式为: class 派生类名:继承方式 基类名 派生类成员声明; ; 说明: 1)、class是关键字,不能省略; 2)、派生类名是定义的新类的标示符;,14.5 继承与派生,3)、继承方式指的是如何访问从基类继承来的成员,继承方式的关键字为public,protected和private,分别表示公有继承、保护继承和私有继承。如果不给出继承方式系统默认为私有继承方式; 4)、继承方式为public时,基类的public成员是派生类的public成员;基类的protected成员为派生类的protected成员。而基类的privated成员是不被继承,不能访问。 5)、继承方式为protected时,基类的public和protected成员均为派生类的protected成员。而基类的privated成员是不被继承,不能访问。 6)、继承方式为private时,基类的public和protected成员均为派生类的privated成员。而基类的privated成员是不被继承,不能访问。,14.5 继承与派生,【例1425】 基类与派生类 #include class Base/定义基类 protected: int m_B;/保护数据成员 public: void Set_B(int);/设置m_B的值 void Display_B();/显示m_B的值 ;,14.5 继承与派生,void Base:Set_B(int x)/设置m_B的值 m_B=x; void Base:Display_B()/显示m_B的值 cout“m_B的值为:“m_Bendl; class Derived : public Base/定义派生类 public : void Display_BD();/显示10*m_B的值 ; void Derived:Display_BD()/显示10*m_B的值 cout“10*m_B的值为:“10*m_Bendl; ,14.5 继承与派生,void main() cout“基类的情况“endl; Base b; /声明基类对象 b.Set_B(6); /设置m_B的值为6 b.Display_B(); /显示m_B的值 cout“派生类的情况“endl; Derived d; /声明派生类 d.Set_B(8); /调用继承的函数设置m_B的值为8 d.Display_B(); /调用继承的函数显示m_B的值 d.Display_BD(); /调用派生类新的函数显示10*m_B的值 ,14.5 继承与派生,运行结果为: 图14.5 程序运行结果,14.5 继承与派生,14.5.2 多重继承 在C+中,继承时,基类可以是一个也可以有多个。如果只有一个基类为单继承。如果有多个基类,则为多重继承。其派生类的定义格式为: class 派生类名:继承方式1 基类1,继承方式2 基类2, 类成员; ; 说明:继承方式只能控制其后面最近的基类。,14.5 继承与派生,【例1426】 多重继承 #include class Base1/定义基类1 protected: int m_B1;/保护数据成员 public: void Set_B1(int);/设置m_B1的值 void Display_B1();/显示m_B1的值 ;,14.5 继承与派生,/成员函数定义 void Base1:Set_B1(int x)/设置m_B1的值 m_B1=x; void Base1:Display_B1()/显示m_B1的值 cout“m_B1的值为:“m_B1endl; class Base2/定义基类2 protected: int m_B2;/保护数据成员 public: void Set_B2(int);/设置m_B2的值 void Display_B2();/显示m_B2的值 ;,14.5 继承与派生,/成员函数定义 void Base2:Set_B2(int x)/设置m_B2的值 m_B2=x; void Base2:Display_B2()/显示m_B2的值 cout“m_B2的值为:“m_B2endl; class Derived : public Base1,public Base2/定义派生类 public : void Display

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论