《apl03.类深入剖析II》由会员分享,可在线阅读,更多相关《apl03.类深入剖析II(54页珍藏版)》请在金锄头文库上搜索。
1、高级语言程序设计-2C+1 1第三章 类:深入剖析(II)2 2内容安排内容安排y常量常量y组成:对象作为类的成员组成:对象作为类的成员y友元函数和友元类友元函数和友元类ythis指针和动态内存分配指针和动态内存分配y静态类成员静态类成员内容安排内容安排y常量常量y组成:对象作为类的成员组成:对象作为类的成员y友元函数和友元类友元函数和友元类ythis指针和动态内存分配指针和动态内存分配y静态类成员静态类成员常量常量yconst类型修饰符:常量说明符类型修饰符:常量说明符是是constant的缩写,的缩写, “恒定不变恒定不变”的意的意思,被其修饰的东西都受到强制保护,思,被其修饰的东西都受到
2、强制保护,可以预防意外的变动,提高程序健壮性可以预防意外的变动,提高程序健壮性 在变量说明语句中,在变量说明语句中,const 用于用于冻结一冻结一个变量,使其在程序中不能被修改个变量,使其在程序中不能被修改在用在用const 声明变量时,声明变量时, 必须对该变量必须对该变量进行初始化进行初始化很多很多C+程序设计书籍建议:程序设计书籍建议:“Use const whenever you need”const关键字主要使用场合关键字主要使用场合y1. 修饰一个简单的变量修饰一个简单的变量y2. 修饰函数的输入参数修饰函数的输入参数y3. 修饰函数的返回值修饰函数的返回值y4. 修饰类的成员函
3、数修饰类的成员函数1. 修饰一个简单的变量修饰一个简单的变量constconst intint a = 1; a = 1; intint constconst a = 1; a = 1; constconst 可以放在类型修饰符的可以放在类型修饰符的可以放在类型修饰符的可以放在类型修饰符的前面和后面,没有任何差别,前面和后面,没有任何差别,前面和后面,没有任何差别,前面和后面,没有任何差别,功能:定义一个常量功能:定义一个常量功能:定义一个常量功能:定义一个常量a a,其值为是,其值为是,其值为是,其值为是1 1constconst intint* * p1 = &b; p1 = &b; in
4、tint constconst* * p2 = &b; p2 = &b; intint * *constconst p3 = &b; p3 = &b; 功能:指向功能:指向功能:指向功能:指向intint常量常量常量常量的指针的指针的指针的指针功能:指向功能:指向功能:指向功能:指向intint常量常量常量常量的指针的指针的指针的指针功能:指向功能:指向功能:指向功能:指向intint变量变量变量变量的的的的常量指针常量指针常量指针常量指针在常量指针(在常量指针(在常量指针(在常量指针(const pointerconst pointer)中,)中,)中,)中,“const”“const”永远
5、出现在永远出现在永远出现在永远出现在“*”“*”之后之后之后之后const_cast转换常量性转换常量性#include #include using std:cout;using std:cout;using std:endl;using std:endl;int main()int main()int* p1;int* p1;const int abc=10;const int abc=10;p1=&abc; /A p1=&abc; /A 编译错误编译错误编译错误编译错误p1=const_cast (&abc); /Bp1=const_cast (&abc); /B*p1=5;*p1=5;
6、coutabc=abccoutabc=abcn*p1=*p1endl;n*p1=*p1endl;return 0;return 0; 2. 修饰函数的输入参数修饰函数的输入参数yconst修饰输入参数,不能修饰输出参数:修饰输入参数,不能修饰输出参数:输入参数采用输入参数采用“ “指针传递指针传递指针传递指针传递” ”,那么加,那么加const修修饰可以防止意外地改动该指针,起到保护作饰可以防止意外地改动该指针,起到保护作用用输入参数采用输入参数采用“ “值传递值传递值传递值传递” ”,由于函数将自动,由于函数将自动产生临时变量用于复制该参数,该输入参数产生临时变量用于复制该参数,该输入参数本
7、来就无需保护,所以不要加本来就无需保护,所以不要加const修饰修饰对于非内部数据类型的输入参数,应该将对于非内部数据类型的输入参数,应该将“值传递值传递”的方式改为的方式改为“ “const const 引用传递引用传递引用传递引用传递” ”,目的是提高效率。例如将目的是提高效率。例如将void Func(T a) 改为改为void Func(const T &a) ,如类的拷贝构造函,如类的拷贝构造函数数 void strcpy(char *strDestination, const char *strSource);其中其中strSource是输入参数,是输入参数,strDestinat
8、ion是输出参数。给是输出参数。给strSource加上加上const修饰后,如果函数体内的语句试图改动修饰后,如果函数体内的语句试图改动strSource的内容,编译器将指出错误的内容,编译器将指出错误3. 修饰函数的返回值修饰函数的返回值y如果给以如果给以“指针传递指针传递”方式的函数返回值方式的函数返回值加加const修饰,那么函数返回值(即指针)修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给的内容不能被修改,该返回值只能被赋给加加const修饰的同类型指针修饰的同类型指针y如果函数返回值采用如果函数返回值采用“值传递方式值传递方式”,由,由于函数会把返回值复制到外部
9、临时的存储于函数会把返回值复制到外部临时的存储单元中,加单元中,加const修饰没有任何价值修饰没有任何价值y函数返回值采用函数返回值采用“引用传递引用传递”的场合并不的场合并不多,这种方式一般只出现在类的赋值函数多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达中,目的是为了实现链式表达 ;如果将;如果将赋值函数的返回值加赋值函数的返回值加const修饰,那么该返修饰,那么该返回值的内容不允许被改动回值的内容不允许被改动函数:函数:const char * GetString(void);如下语句将出现编译错误:如下语句将出现编译错误:char *str = GetString(
10、);正确的用法是:正确的用法是:const char *str = GetString();const char *str = GetString();4. 修饰类的成员函数修饰类的成员函数y任何任何不会修改数据成员不会修改数据成员的成员函数的成员函数都应该声明为都应该声明为const类型类型const关键字放在成员函数定义的最后关键字放在成员函数定义的最后如果在编写如果在编写const成员函数时,不慎修成员函数时,不慎修改了数据成员,或者调用了其它非改了数据成员,或者调用了其它非const成员函数,编译器将指出错误成员函数,编译器将指出错误为时间类添加为时间类添加const约束约束class
11、 Timeclass Timepublic:public:Time(const Time&);Time(const Time&); int getHour()int getHour() constconst; ; int getMinute()int getMinute() constconst; ; int getSecond()int getSecond() constconst; ;void printUniversal()void printUniversal() constconst; ;void printStandard();/?void printStandard();/?;
12、;void Time:printUniversal() const cout setfill(0)setw(2)hour : setw(2)minute:setw(2)a.xa.z; void out(const A& a)void out(const A& a) couta.x a.zendl; 友元成员友元成员y友元成员友元成员是其他某个类的成员函数,是当前类的友是其他某个类的成员函数,是当前类的友元元friend 返回类型返回类型 类名类名:函数名函数名(参数列表参数列表);y说明:说明:1.友元成员的声明,除了前面冠以友元成员的声明,除了前面冠以“friend”外,还要注明所属类的类名
13、外,还要注明所属类的类名2.友元成员应该在自己所属类的定义体中友元成员应该在自己所属类的定义体中进行成员函数声明(或定义)进行成员函数声明(或定义)友元类友元类y友元类友元类是一个类,而且是另一个类的友元是一个类,而且是另一个类的友元friend class 类名类名;y说明:说明:类类A和和B,B被声明为被声明为A的友元类,则的友元类,则B类的所有成员函数都可以访问类的所有成员函数都可以访问A类的私类的私有成员有成员友元类范例友元类范例class A int x,y;class A int x,y;public:public: A(int xx=0,int yy=0):x(xx),y(yy)
14、 A(int xx=0,int yy=0):x(xx),y(yy) friend class B;friend class B; ;class B char n20;class B char n20;public:public: B(char nn ) strcpy(n,nn); B(char nn ) strcpy(n,nn); void sh(const A& a1) void sh(const A& a1) coutn: coutn: a1.xa1.x a1.ya1.yendl; endl; void sum(const A& a1) void sum(const A& a1) cout
15、n: coutn: a1.x+a1.ya1.x+a1.yendl; endl; ; ;友元关系一些注意问题友元关系一些注意问题y友元关系是友元关系是“给予给予”,而不是,而不是“索取索取”的的y友元关系既不对称也不能传递友元关系既不对称也不能传递y尽管类定义中有友元函数的原型,但友元尽管类定义中有友元函数的原型,但友元函数然仍不是成员函数函数然仍不是成员函数yprivate、protected和和public的成员访问符的成员访问符号与友元关系的声明无关号与友元关系的声明无关因此友元关系声明可以放在类定义中任何地因此友元关系声明可以放在类定义中任何地方方习惯:将类中所有友元关系的声明放在类定习
16、惯:将类中所有友元关系的声明放在类定义最前面,并不加任何成员访问说明符义最前面,并不加任何成员访问说明符内容安排内容安排y常量常量y组成:对象作为类的成员组成:对象作为类的成员y友元函数和友元类友元函数和友元类ythis指针和动态内存分配指针和动态内存分配y静态类成员静态类成员使用使用this指针指针yC+为每个类提供一个为每个类提供一个this指针指针指向指向“当前当前”对象对象通过通过this指针可以访问当前对象的成员指针可以访问当前对象的成员y说明说明在非静态成员函数中使用在非静态成员函数中使用this指针指针友元函数不是成员函数,没有友元函数不是成员函数,没有this指针指针注意友元成
17、员函数中的注意友元成员函数中的this指针所指向指针所指向的对象的对象this指针的用法指针的用法/p408, Fig 10.17class Test public: Test( int = 0 ); void print() const;private: int x;Test:Test( int value ) : x(value) void Test:print() const cout x = x; cout x = x; cout n(*this).x = (*this).x = 0 & h = 0 & m 、.*、-*)可直接通过类名访问可直接通过类名访问(:)类名类名:静态成员静态
18、成员可以没有声明类的任何对象时就使用静可以没有声明类的任何对象时就使用静态类成员态类成员使用静态数据成员使用静态数据成员class Aclass A int a; int a; static int x;static int x;public: public: A(int aa=0):a(aa) A(int aa=0):a(aa) x+; x+; couta.x=xendl; couta.x=xendl; static void view()static void view() coutA:x=xendl; coutA:x=xendl; ; ;/ /初始化静态数据成员初始化静态数据成员初始化静
19、态数据成员初始化静态数据成员int A:x(900); /int A:x(900); /或者:或者:或者:或者:int A:x=900; int A:x=900; void main() A:view(); A a1,a2; A:view(); a2.view();/执行结果:执行结果: A:x=900 a.x=901 a.x=902 A:x=902 A:x=902使用静态类成员使用静态类成员yP415, Fig 10.21Fig 10.23利用静态类成员统计类对象的个数利用静态类成员统计类对象的个数(统统计员工的个数计员工的个数)class Employee public: Employee
20、(const char* const, const char* const); Employee(); static int getCount(); private: static int count; / 统计类对象的数量统计类对象的数量;使用静态类成员使用静态类成员int Employee:count = 0; /初始个数为初始个数为0Employee:Employee() firstName = new char strlen( first ) + 1 ; strcpy( firstName, first ); lastName = new char strlen( last ) + 1
21、 ; strcpy( lastName, last ); count+; / 对象个数对象个数+1 Employee:Employee() delete firstName; delete lastName; count-; /对象个数对象个数-1上机实验上机实验2实验内容实验内容y参考参考Fig10.1210.13、Fig10.2110.22,实现学生类实现学生类CStudent;具体要求如下:;具体要求如下:数据成员:姓名数据成员:姓名name,必须使用,必须使用char*类型(不能使类型(不能使用用char,或或string类型),在构造和析构函数中实现类型),在构造和析构函数中实现动态
22、内存分配动态内存分配组成数据成员:出生日期组成数据成员:出生日期birthDate,使用实验,使用实验1所完所完成的成的CDate类型类型静态数据成员:学生数量静态数据成员:学生数量count,用于统计在程序中,用于统计在程序中产生学生对象的个数产生学生对象的个数提供构造函数、拷贝构造函数和析构函数提供构造函数、拷贝构造函数和析构函数提供必要的提供必要的get和和set函数,存取私有数据成员函数,存取私有数据成员编写编写main函数,测试所要求的功能函数,测试所要求的功能按标准按标准C+语法编写程序语法编写程序作业提交方式作业提交方式y1. 准备准备本机新建一目录,以自己的学号、命名、作业次数
23、,本机新建一目录,以自己的学号、命名、作业次数,如:如:“张三张三2”将本次作业所完成的将本次作业所完成的5个源代码文件放在该目录下个源代码文件放在该目录下(日日期类和学生类的期类和学生类的2个个.h和和3个个cpp),打包压缩为一个文,打包压缩为一个文件件“张三张三2.zip”后提交后提交y2. 提交提交登录,用户名密码均为您的学号;登录时页面出错的登录,用户名密码均为您的学号;登录时页面出错的话,请重新刷新即可话,请重新刷新即可选择菜单选择菜单“协同学习协同学习/教学辅助教学辅助”,再选择,再选择“高级语高级语言程序设计言程序设计2”课程,单击课程,单击“课程作业课程作业”菜单,在菜单,在
24、“作业作业2-学生类学生类”下面选择选择下面选择选择“提交作业提交作业”链接,提链接,提交压缩好的作业即可交压缩好的作业即可注意事项:必须用注意事项:必须用IE提交,提交,IE6可以直接提交,可以直接提交,IE7及以上版本需要修改设置,将及以上版本需要修改设置,将“将文件上载到服务将文件上载到服务器时包含本地目录路径器时包含本地目录路径”启用启用 请预习请预习y教材第教材第11章:运算符重载章:运算符重载11.111.7、11.911.14y主要内容主要内容运算符重载的基本原理和运算符函数运算符重载的基本原理和运算符函数流运算符的重载流运算符的重载一元、二元运算符的重载,注意返回类一元、二元运算符的重载,注意返回类型的区别型的区别特殊的运算符:特殊的运算符:=、()、类型转换函数、类型转换函数等等