900 likes | 1.06k Views
第 10 章 C++ 面向对象程序设计. 《 C 语言程序设计 》 (Visual C++ 6.0 环境). 本章导读 C 语言是一种结构化程序设计语言,它是面向过程的,在处理较小规模的程序时一般比较容易实现,而当程序规模较大时, C 语言就显示出了它的不足。在这种情况下 C++ 应运而生, C++ 语言是从 C 语言演变而来的,它保留了 C 语言的所有优点,同时也增加了面向对象的功能。现在 C++ 已成为程序设计中应用最广泛的一种语言。. 本章主要知识点 (1) C++ 面向对象的程序实例 (2) 类与对象 (3) 继承与派生 (4) 运算符重载. 返回本书目录.
E N D
第10章 C++面向对象程序设计 《 C语言程序设计》(Visual C++ 6.0环境) • 本章导读C语言是一种结构化程序设计语言,它是面向过程的,在处理较小规模的程序时一般比较容易实现,而当程序规模较大时,C语言就显示出了它的不足。在这种情况下C++应运而生,C++语言是从C语言演变而来的,它保留了C语言的所有优点,同时也增加了面向对象的功能。现在C++已成为程序设计中应用最广泛的一种语言。 • 本章主要知识点 • (1)C++面向对象的程序实例 • (2)类与对象 • (3)继承与派生 • (4)运算符重载 返回本书目录
10.1C++面向对象的程序实例 《 C语言程序设计》(Visual C++ 6.0环境) 10.2 类与对象 第10章 C++面向对象程序设计 10.3 继承与派生 10.4 运算符重载 10.5 综合实训 返回本章导读
《 C语言程序设计》(Visual C++ 6.0环境) 10.1 C++面向对象的程序实例 10.1.1 C++面向对象的程序实例 10.1.2 C++语言概述 返回本章目录
《 C语言程序设计》(Visual C++ 6.0环境) 1. C++程序实例(1) 10.1.1 C++面向对象的程序实例 2. C++程序实例(2) 3. C++程序实例(3) 返回本节目录
1.C++程序实例1 《 C语言程序设计》(Visual C++ 6.0环境) 【例10.1】定义一个矩形类。(程序名为l10_1.cpp。) #include<iostream.h> class rectangle //定义一个矩形类 { public: rectangle(float len,float wid) //构造函数 { length=len; width=wid; } float GetArea(); //声明成员函数,计算矩形面积 float GetPerimeter(); //声明成员函数,计算矩形周长 ~rectangle(){} //析构函数 private: float length; //私有数据 float width;}; 10.1.1 C++面向对象的程序实例 返回本节目录
float rectangle::GetArea() //成员函数的具体实现 { return length*width; } float rectangle::GetPerimeter() //成员函数的具体实现 { return 2*(length+width); } void main() { float l,w; cout<<"请输入矩形的长和宽:"; cin>>l>>w; rectangle x(l,w); //定义一个矩形类对象 cout<<x.GetArea()<<endl; cout<<x.GetPerimeter()<<endl; //调用成员函数 } 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.1 C++面向对象的程序实例 返回本节目录
实例1的功能是定义一个矩形类,该类有长和宽两个数据成员,用来描述矩形的静态特征(属性),有构造函数用来用初始化类对象,另外还有计算面积和周长两个成员函数作为该类的外部接口,供类外的程序访问。当用户输入矩形的长和宽之后,将构造一个实例矩形,并输出矩形的面积和周长。实例1的功能是定义一个矩形类,该类有长和宽两个数据成员,用来描述矩形的静态特征(属性),有构造函数用来用初始化类对象,另外还有计算面积和周长两个成员函数作为该类的外部接口,供类外的程序访问。当用户输入矩形的长和宽之后,将构造一个实例矩形,并输出矩形的面积和周长。 例如用户输入5,6< CR >,则输出结果为:3022 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.1 C++面向对象的程序实例 返回本节目录
2.C++程序实例2 【例10.2】类的派生。(程序名为l10_2.cpp。) #include<iostream.h> class rectangle //定义矩形类 { public: void InitRect(float len,float wid) //定义类的成员函数 { length=len; width=wid; } float GetArea(); float GetPerimeter(); private: //定义私有成员变量 float length; float width; }; float rectangle::GetArea() //成员函数实现 { return length*width;} 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.1 C++面向对象的程序实例 返回本节目录
float rectangle::GetPerimeter() //成员函数实现 { return 2*(length+width); } class square:public rectangle //从矩形类中派生新类(正方形类) {public: void InitSquare(float b){InitRect(b,b);} //新增的成员函数(初始化 }; //正方形) void main() { square x; //声明正方形类对象 x.InitSquare(8); //调用正方形类新增的成员函数 cout<<x.GetArea()<<endl; //调用从矩形类中继承下来的成员函数cout<<x.GetPerimeter()<<endl; //调用从矩形类中继承下来的成员 } //函数(GetPerimeter) 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.1 C++面向对象的程序实例 返回本节目录
实例2的功能是先定义一个矩形类,然后从该矩形类中派生出一个新的正方形类(正方形是矩形的一个特例)。程序中先声明一个正方形类对象,然后将其初始化为边长为8的正方形,再调用从矩形类中继承下来的计算面积和周长两个函数,计算出正方形的面积和周长。该程序的输出结果为:实例2的功能是先定义一个矩形类,然后从该矩形类中派生出一个新的正方形类(正方形是矩形的一个特例)。程序中先声明一个正方形类对象,然后将其初始化为边长为8的正方形,再调用从矩形类中继承下来的计算面积和周长两个函数,计算出正方形的面积和周长。该程序的输出结果为: 6432 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.1 C++面向对象的程序实例 返回本节目录
3.C++程序实例3 《 C语言程序设计》(Visual C++ 6.0环境) 【例10.3】“+”运算符重载。(程序名为l10_3.cpp。) #include<iostream.h> class rectangle //定义一个矩形类 {public: rectangle(float len=0,float wid=0) //构造函数 { length=len; width=wid; } float GetArea(){return length*width;} //成员函数(计算面积) rectangle operator +(rectangle a2) //将"+"运算符重载 { rectangle a; //用于两个矩形对象相加 a.length=length; a.width=width+a2.GetArea()/length; return rectangle(a.length,a.width); } 10.1.1 C++面向对象的程序实例 返回本节目录
private: //私有成员变量 float length; float width; }; void main() { rectangle x(5,9),y(5,6),z; //声明类对象 cout<<"第一个矩形面积为:"<<x.GetArea()<<endl; cout<<"第二个矩形面积为:"<<y.GetArea()<<endl; z=x+y; //对两个矩形相加 cout<<"两个矩形面积之和为:"<<z.GetArea()<<endl; } 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.1 C++面向对象的程序实例 实例3的功能是先定义一个矩形类,然后将“+”运算符重载为可以使两个矩形类对象相加。该程序的输出结果为:第一个矩形面积为:45第二个矩形面积为:30两个矩形面积之和为:75 返回本节目录
由于结构化程序设计自身的不足,在20世纪80年代出现了面向对象程序设计方法,C++语言也由此而产生。由于结构化程序设计自身的不足,在20世纪80年代出现了面向对象程序设计方法,C++语言也由此而产生。 面向对象程序设计(Object-Oriented programming,简称OOP)设计的出发点就是为了能更直接的描述客观世界中存在的事物(即对象)以及它们之间的关系。面向对象程序设计是对结构化程序设计的继承和发展,它认为现实世界是由一系列彼此相关且能相互通信的实体组成,这些实体就是面向对象方法中的对象,而对一些对象的共性的抽象描述,就是面向对象方法中的类。类是面向对象程序设计的核心。 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.2 C++语言概述 返回本节目录
C++是目前最流行的面向对象程序设计语言。它在C语言的基础上进行了改进和扩充,并增加了面向对象程序设计的功能,更适合于开发大型的软件。C++是由贝尔实验室在C语言的基础开发成功的,C++保留了C语言原有的所有优点,同时与C语言又完全兼容。它既可以用于结构化程序设计,又可用于面向对象程序设计,因此C++是一个功能强大的混合型程序设计语言。 C++最有意义的方面是支持面向对象程序设计的特征。虽然与C语言的兼容性使得C++具有双重特点,但它在概念上和C语言是完全不同的,学习C++应该按照面向对象程序的思维去编写程序。 《 C语言程序设计》(Visual C++ 6.0环境) 10.1.2 C++语言概述 返回本节目录
10.2.1 面向对象的基本概念 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.2 类的构造与封装 10.2 类与对象 10.2.3 创建对象 10.2.4 友元 10.2.5 模板 10.2.6 程序实训 返回本章目录
1. 对象 《 C语言程序设计》(Visual C++ 6.0环境) 从一般意义上讲,客观世界中任何一个事物都可以看成是一个对象。例如一本书,一名学生等。对象具有自己的静态特征和动态特征。静态特征可以用某种数据来描述,如一名学生的身高、年龄、性别等;动态特征是对象所表现的行为或具有的功能,如学生学习、运动、休息等。 面向对象方法中的对象是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位,对象由一组属性和一组行为构成。属性是用来描述对象静态特征的数据项,行为是用来描述对象动态特征的操作序列。 10.2.1 面向对象的基本概念 返回本节目录
2.类 《 C语言程序设计》(Visual C++ 6.0环境) 许多对象具有相同的结构和特性,例如不管是数学书还是化学书,它们都具有大小、定价、编者等特性。在现实生活中,我们通常将具有相同性质的事物归纳、划分成一类,例如数学书和化学书都属于书这一类。同样在面向对象程序设计中也会采用这种方法。面向对象方法中的类是具有相同属性和行为的一组对象的集合。 类代表了一组对象的共性和特征,类是对象的抽象,而对象是类的具体实例。例如,家具设计师按照家具的设计图做成一把椅子,那么设计图就好比是一个类,而做出来的椅子则是该类的一个对象,一个具体实例。拿【例10.1】中定义的矩形类来说,该类只是所有矩形的一个蓝本,它只是代表了矩形的一些特征,而该类的实例则是一个特定的矩形。 10.2.1 面向对象的基本概念 返回本节目录
1.类的封装 《 C语言程序设计》(Visual C++ 6.0环境) 类的封装就是将对象的属性和行为结合成一个独立的实体,并尽可能隐蔽对象的内部细节,对外形成一道屏障,只保留有限的对外接口使之和外界发生联系。类的成员包括数据成员和成员函数,分别描述类所表达问题的属性和行为。对类成员的访问加以控制就形成了类的封装,这种控制是通过设置成员的访问权限来实现的。 在面向对象程序设计中,通过封装将一部分行为作为外部接口,而将数据和其它行为进行有效的隐蔽,就可以达到对数据访问权限的合理控制。把整个程序中不同部分的相互影响减少到最低限度。 10.2.2 类的构造与封装 返回本节目录
2.类的定义 《 C语言程序设计》(Visual C++ 6.0环境) 类定义的一般格式为: class 类名称{public:公有数据和成员函数 /*外部接口*/ protected:保护数据的成员函数 private:私有数据和成员函数}; 10.2.2 类的构造与封装 返回本节目录
关键字class说明了类定义的开始,类中所有的内容用大括号括起来。类的成员可分为三种级别的访问权限:关键字class说明了类定义的开始,类中所有的内容用大括号括起来。类的成员可分为三种级别的访问权限: public(公有的):说明该成员是公有的,它不但可以被类的成员函数访问,而且可以被外界访问,所以说公有类型定义了类的外部接口。 Protected(保护的):说明该成员只能被该类的成员函数和该类的派生类的成员函数访问。 Private(私有的):说明该成员只能被类的成员函数访问,外界不能直接访问它。类的数据成员一般都应该声明为私有成员。 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.2 类的构造与封装 返回本节目录
3.类的成员函数 《 C语言程序设计》(Visual C++ 6.0环境) 类的成员函数描述的是类的行为。定义类时在类定义体中给出函数的声明,说明函数的参数列表和返回值类型,而函数的具体实现一般在类定义体之外给出。下面是类外定义成员函数的一般格式: 返回值类型 类名::类成员函数名(参数列表) { 函数体}其中::称为作用域分辨符。用它可以限制要访问的成员所在的类的名称。 10.2.2 类的构造与封装 返回本节目录
4.构造函数和析构函数 《 C语言程序设计》(Visual C++ 6.0环境) 在建立一个对象时,常常需要作一些初始化工作,而当对象使用结束时,又需要作一些清理工作。在C++中提供了两个特殊的成员函数来完成这两项工作,那就是构造函数和析构函数。 构造函数的作用就是在对象在被创建时利用特定的值构造对象,将对象初始化。构造函数完成的是一个从一般到具体的过程。需要注意的是构造函数同其它的成员函数不同,它不需要用户触发,而是在创建对象时由系统自动调用,其它任何过程都无法再调用构造函数。构造函数的函数名必须与类名相同,而且不能有返回值,也不需加void类型声明。构造函数可以带参数也可以不带参数。构造函数一般定义为公有类型。 10.2.2 类的构造与封装 返回本节目录
析构函数也是类的一个公有成员函数,其作用与构造函数正好相反,它是用来在对象被删除前进行一些清理工作。析构函数调用之后,对象被撤消了,相应的内存空间也将被释放。析构函数名也应与类名相同,只是函数名前加一个波浪符“~”,以区别于构造函数。析构函数不能有任何参数,且不能有返回值。如果不进行显式说明,系统会自动生成缺省的析构函数,所以一些简单的类定义中没有显式的析构函数。析构函数也是类的一个公有成员函数,其作用与构造函数正好相反,它是用来在对象被删除前进行一些清理工作。析构函数调用之后,对象被撤消了,相应的内存空间也将被释放。析构函数名也应与类名相同,只是函数名前加一个波浪符“~”,以区别于构造函数。析构函数不能有任何参数,且不能有返回值。如果不进行显式说明,系统会自动生成缺省的析构函数,所以一些简单的类定义中没有显式的析构函数。 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.2 类的构造与封装 5.构造函数与析构函数应用实例 返回本节目录
【例10.4】程序名为l10_4.cpp。#include<iostream.h>class A //定义类A { public: A(){ cout<<“构造函数被调用”<<endl; //构造函数} void disp() //成员函数{ cout<<“构造函数与析构函数应用举例”<<endl; } ~A() //析构函数{ cout<<"析构函数被调用"<<endl; }}; 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.2 类的构造与封装 返回本节目录
void main(){ A a; //声明类对象,自动调用构造函数a.disp(); //调用成员函数,对象使用结束时//自动调用析构函数} 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.2 类的构造与封装 6.实例分析 程序在声明A类的对象时,系统会自动调用构造函数,因而先执行构造函数中的输出语句,输出“构造函数被调用”,接下来调用disp成员函数,执行disp成员函数中的输出语句,输出“构造函数与析构函数应用举例”,最后程序在退出前由系统自动调用析构函数,执行析构函数中的输出语句,输出“析构函数被调用”,因此程序的输出结果为:构造函数被调用 构造函数与析构函数应用举例 析构函数被调用 返回本节目录
通过使用数组,我们可以对大量的数据和对象进行有效的管理,但对于许多程序,在运行之前,我们并不能确切地知道数组中会有多少个元素。例如,一个网络中有多少个可用节点,一个CAD系统中会用到多少个形状等。如果数组开的太大会造成很大的浪费,如果数组较小则又影响大量数据的处理。在C++中,动态内存分配技术可以保证我们在程序运行过程中按实际需要申请适量的内存,使用结束后再进行释放。这种在程序运行过程中申请和释放存储单元的过程称为创建对象和删除对象。通过使用数组,我们可以对大量的数据和对象进行有效的管理,但对于许多程序,在运行之前,我们并不能确切地知道数组中会有多少个元素。例如,一个网络中有多少个可用节点,一个CAD系统中会用到多少个形状等。如果数组开的太大会造成很大的浪费,如果数组较小则又影响大量数据的处理。在C++中,动态内存分配技术可以保证我们在程序运行过程中按实际需要申请适量的内存,使用结束后再进行释放。这种在程序运行过程中申请和释放存储单元的过程称为创建对象和删除对象。 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.3 创建对象 1.new运算符 返回本节目录
C++用new运算符来创建对象。运算符new的功能是动态创建对象,其语法形式为:new 类型名(初值列表);该语句的功能是在程序运行过程中申请用于存放指定类型的内存空间,并用初值列表中给出的值进行初始化。如果创建的对象是普通变量,初始化工作就是赋值,如果创建的对象是某一个类的实例对象,则要根据实际情况调用该类的构造函数。例如:int *p; p=new int(100); //赋值给指针变量例如:rectangle *r; r=new rectangle(5,6); //调用矩形类的构造函数如果创建的对象是数组类型,则应按照数组的结构来创建,其语法形式为: 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.3 创建对象 返回本节目录
一维数组:new 类型名[下标];当数组为一维数组时,下标为数组为元素的个数,动态分配内存时不能指定数组元素的初值。如果内存申请成功,返回一个指向新分配内存的首地址的指定类型的指针,如果失败返回0。例如:int *p; p=new int[10];多维数组:new 类型名[下标1][下标2]……;当数组为多维数组时,返回一个指向新分配内存的首地址的指针,但该指针的类型为指定类型的数组。数组元素的个数为除最左边一维外下标的乘积。例如:int (*p)[5]; p=new int[10][5]; 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.3 创建对象 返回本节目录
2.delete运算符 《 C语言程序设计》(Visual C++ 6.0环境) 运算符delete的功能是删除由new运算符创建的对象,释放指针指向的内存空间,其语法形式为:delete 指针名;例如:int *p; p=new int(100); delete p;如果new 运算符创建的对象是数组,则删除对象时应使用的语法形式为:delete []指针名;例如:int *p; p=new int[10]; delete []p; 10.2.3 创建对象 返回本节目录
3.C++程序实例 《 C语言程序设计》(Visual C++ 6.0环境) 【例10.5】类对象的创建与删除。(程序名为l10_5.cpp。)#include<iostream.h>class rectangle //定义一个矩形类 {public: rectangle(float len,float wid) //构造函数{ length=len; width=wid; } float GetArea(); //成员函数private: float length; float width;}; 10.2.3 创建对象 返回本节目录
float rectangle::GetArea() //成员函数实现 { return length*width;}void main(){ rectangle *r; //定义指向rectangle类的指针变量r r=new rectangle(10,5); //创建rectangle类对象cout<<r->GetArea()<<endl; delete r; //删除对象} 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.3 创建对象 4.C++程序实例分析 程序中先建立了一个rectangle类,然后在主函数中定义了一个指向rectangle类的指针变量r,用new在内存中开辟一段空间以存放rectangle类对象,这时会自动调用构造函数来初始化该对象,接下来使用指向rectangle类的指针变量r得到矩形的面积,最后用delete删除对象,释放该空间。 返回本节目录
《 C语言程序设计》(Visual C++ 6.0环境) 1. 友元概述 10.2.4 友元 2. 友元函数 3. 友元类 返回本节目录
1.友元概述 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 在程序设计过程中,假如用户建立了一个类,这个类的数据成员被定义为私有,这时如果想把该数据存取到某个函数(非该类的成员函数)中,那么这样作肯定是不被允许的。但是有时候一些非成员函数需要亲自访问类中的某些私有数据,那么这时候就需要用到友元。友元提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。通过友元,一个普通函数或类的成员函数可以访问到封装于其它类中的数据。友元的作用在于提高程序的运行效率,但同时它也破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。 返回本节目录
2.友元函数 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 友元函数是在类定义中由关键字friend修饰的非成员函数。友元函数可以是一个普通函数,也可以其它类中的一个成员函数,它不是本类的成员函数,但它可以访问本类的私有成员和保护成员。友元函数需要在类的内部进行声明。其格式如下: class 类名称 { 类的成员声明 friend 返回类型 友元函数名(参数列表); 类的成员声明 } 返回本节目录
【例10.6】使用友元函数计算两点间的距离。 程序名为l10_6.cpp。 #include <iostream.h>#include <math.h>class Point //定义Point类(点){public: Point(double xx,double yy) //构造函数{x=xx; y=yy;} void Getxy(); //成员函数声明friend double Distance(Point &a,Point &b);//友元函数声明private: double x,y; //私有成员(点的坐标)}; 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 返回本节目录
void Point::Getxy() //成员函数实现{cout<<“(”<<x<<“,”<<y<<“)”; //输出点的坐标}double Distance(Point &a, Point &b) //友元函数实现{ double dx = a.x - b.x; //访问私有成员double dy = a.y - b.y; return sqrt(dx*dx+dy*dy); //两点距离}void main(){ Point p1(3.0, 4.0), p2(6.0, 8.0); //定义Point类对象p1.Getxy(); //调用成员函数p2.Getxy(); cout<<“\nThe istance is ”<<Distance(p1, p2)<<endl; //调用友元函数} 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 返回本节目录
实例说明:程序在类定义体内声明了友元函数的原形,在声明时函数名前加friend关键字进行修饰,友元函数的具体实现在类外给出,可以看出友元函数通过对象名可直接访问Point类的私有成员,而不需要借用外部接口Getxy。在调用友元函数时同调用普通函数一样,采用直接调用方法,而不需要像调用类的成员函数那样必须通过对象。该程序的输出结果为:实例说明:程序在类定义体内声明了友元函数的原形,在声明时函数名前加friend关键字进行修饰,友元函数的具体实现在类外给出,可以看出友元函数通过对象名可直接访问Point类的私有成员,而不需要借用外部接口Getxy。在调用友元函数时同调用普通函数一样,采用直接调用方法,而不需要像调用类的成员函数那样必须通过对象。该程序的输出结果为: (3,4)(6,8) The distance is 5 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 返回本节目录
3.友元类 《 C语言程序设计》(Visual C++ 6.0环境) 同函数一样,类也可以声明为另一个类的友元,这时称为友元类。当一个类作为另一个类的友元时,这个类的所有成员函数都将是另一个类的友元函数。 友元类的一般格式为: class 类A { 类A的成员声明 friend class 类B; 类A的成员声明 } 10.2.4 友元 返回本节目录
【例10.7】程序名为l10_7.cpp。 #include<iostream.h> class A //定义类A { public: A(int xx,int yy) //类A的构造函数 { x=xx; y=yy; } friend class B; //声明类B为类A的友元类 private: int x,y; }; class B //定义类B {public: void disp1(A s) {cout<<"disp1调用了类A的私有成员x:"<<s.x<<endl;} //类B的成员函数访问类A的私有成员 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 返回本节目录
void disp2(A s) { cout<<"disp2调用了类A的私有成员y:"<<s.y<<endl;} //类B的成员函数访问类A的私有成员};void main() { A a(5,9); //声明A类对象 B b; //声明B类对象 b.disp1(a); //调用B类的成员函数 b.disp2(a); } 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.4 友元 程序中定义了A和B两个类,其中类B为类A的友元类,定义时在类A的内部声明类B,而类B的具体实现过程是在类A的外部。类B中有两个成员函数disp1和disp2,根据友元类的概念,这两个成员函数都成为类A的友元函数,所以它们都可以访问类A的私有成员x和y。该程序的输出结果为: disp1调用了类A的私有成员x:5 disp2调用了类A的私有成员y:9 返回本节目录
1.函数模板 《 C语言程序设计》(Visual C++ 6.0环境) 前面章节中我们学习了重载函数,使用重载函数可以处理多种数据类型,但是即使设计为重载函数也只是使用相同的函数名,函数体仍然要分别定义。 使用函数模板则不同了,函数模板可以用来创建一个通用功能的函数,以支持多种不同的参数,简化重载函数的函数体设计。函数模板的定义形式为: template <typename 标识符> 函数定义 10.2.5 模板 返回本节目录
【例10.8】使用函数模板。(程序名为l10_8.cpp。)【例10.8】使用函数模板。(程序名为l10_8.cpp。) #include <iostream.h> template <typename T> T max(T x,T y) //定义模板函数 { return x>y?x:y; } void main() { int a=6,b=8; cout<<max(a,b)<<endl; double m=10.5,n=8.5; cout<<max(m,n)<<endl; } 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.5 模板 程序中首先定义模板函数max用来取得两个数中相对较大的一个,然后主函数调用该函数,此时编译器将根据实参的类型推导出函数模板的类型参数。例如,当调用max(a,b)时,由于a,b为整型变量,所以模板中类型参数T为int,而调用max(m,n)时,由于m,n为double类型,所以模板中类型参数T为double。 返回本节目录
2.类模板 《 C语言程序设计》(Visual C++ 6.0环境) 使用类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型,包括用户自定义的或系统预定义的。为了定义类模板,应在类的声明之前加上一个模板参数表,参数表里的形式类型名用来说明成员数据和成员函数的类型。类模板的定义形式为:template <class 类型说明符>类定义类模板自身不产生代码,它指定类的一个家族,当被其它代码引用时,类模板才根据引用的需要产生代码。 10.2.5 模板 返回本节目录
【例10.9】使用类模板。(程序名为l10_9.cpp。)#include<iostream.h>template <class T> //类模板,实现对任意数据类型的存取class rectangle //定义一个矩形类rectangle{public: rectangle(T len,T wid) //构造函数{ length=len; width=wid; } T GetArea(); //声明成员函数,计算矩形面积T GetPerimeter(); //声明成员函数,计算矩形周长private: T length; //私有数据,用于任意类型T width;}; template <class T>T rectangle<T>::GetArea() //成员函数的具体实现{ return length*width;} 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.5 模板 返回本节目录
template <class T>T rectangle<T>::GetPerimeter() //成员函数的具体实现{ return 2*(length+width);}void main(){ rectangle<int> x(4,6); //定义rectangle对象(成员函数返回值为int型) rectangle<double> y(5.5,3.8); //定义rectangle对象(成员函数返回值为double型) cout<<“x的面积是:”<<x.GetArea()<<endl; cout<<“x的周长是:”<<x.GetPerimeter()<<endl; cout<<“y的面积是:"<<y.GetArea()<<endl; cout<<"y的周长是:"<<y.GetPerimeter()<<endl; } 程序的执行结果为:x的面积是:24x的周长是:20y的面积是:20.9y的周长是:18.6 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.5 模板 返回本节目录
1.C++程序实例 【例10.10】 日期类应用程序举例。(程序名为l10_10.cpp。)#include<iostream.h>class TDate //日期类的定义{public: TDate(int y, int m, int d); //构造函数int IsLeapYear(); //判断闰年void show(); //显示日期friend int Getyear(TDate date); //友元函数,返回年private: int year,month,day;}; TDate::TDate(int y, int m, int d) //构造函数实现{ year=y; month=m; day=d;} 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.6 程序实训 返回本节目录
int TDate::IsLeapYear(){ return(year%4==0 && year%100!=0) || (year%400==0);}void TDate::show(){ cout<<year<<“年”<<month<<“月”<<day<<“日”<<endl;}int Getyear(TDate date) //友元函数实现{ return date.year;}void main(){ TDate *date; //声明指向TDate类型的指针变量 date=new TDate(2008,10,28); //创建对象 date->show(); //调用成员函数if(date->IsLeapYear()) cout<<Getyear(*date)<<“年是闰年”<<endl; //调用友元函数else cout<<Getyear(*date)<<“年不是闰年"<<endl; delete date; //删除对象} 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.6 程序实训 返回本节目录
2.C++程序实例分析 《 C语言程序设计》(Visual C++ 6.0环境) 10.2.6 程序实训 程序可以分为三个部分,第一部分是CDate类的定义,第二部分是成员函数的实现,第三部分是主函数。类定义中仍然是由成员数据和成员函数组成,其中成员函数作为外部接口。程序中为了说明友元的应用,引入了友元函数,这里可以换成类的成员函数,读者可以自己试一试。主函数中,在定义了指向TDate类型的指针变量之后,使用new运算符创建对象,程序结束时又使用delete运算符删除了对象,释放了内存空间。这种编程方法在以后的程序设计中会经常遇到,读者应该习惯于使用new和delete 进行动态内存管理。 返回本节目录
《 C语言程序设计》(Visual C++ 6.0环境) 10.3.1继承与派生的概念 10.3 继承与派生 10.3.2 派生类 10.3.3派生类的构造函数与析构函数 10.3.4 虚函数 10.3.5 程序实训 返回本章目录
面向对象程序设计过程中,一个很重要的特点就是代码的可重用性。C++是通过继承这一机制来实现代码重用的。所谓继承指的是类的继承,就是在原有类的基础上建立一个新类,新类将从原有类那里得到已有的特性。例如,现有一个学生类,定义了学号、姓名、性别、年龄四项内容,如果我们除了用到以上四项内容外,还需要用到电话和地址等信息,我们就可以在学生类的基础上再增加相关的内容,而不必重头再定义一个类。面向对象程序设计过程中,一个很重要的特点就是代码的可重用性。C++是通过继承这一机制来实现代码重用的。所谓继承指的是类的继承,就是在原有类的基础上建立一个新类,新类将从原有类那里得到已有的特性。例如,现有一个学生类,定义了学号、姓名、性别、年龄四项内容,如果我们除了用到以上四项内容外,还需要用到电话和地址等信息,我们就可以在学生类的基础上再增加相关的内容,而不必重头再定义一个类。 换个角度来说,从已有类产生新类的过程就是类的派生。类的继承与派生允许在原有类的基础上进行更具体、更详细的修改和扩充。新的类由原有的类产生,包含了原有类的关键特征,同时也加入了自己所特有的性质。新类继承了原有类,原有类派生出新类。原有的类我们称为基类或父类,而派生出的类我们称为派生类或子类。比如:所有的windows应用程序都有一个窗口,可以说它们都是从一个窗口类中派生出来的,只不过有的应用程序用于文字处理,有的则应用于图像显示。 《 C语言程序设计》(Visual C++ 6.0环境) 10.3.1 继承与派生的概念 返回本节目录