16:12:111C++程序设计教程(第二版)第八章类Chapter8Class清华大学出版社钱能16:12:112类类是一种可以作为交易的概念代码.类是自定义的数据类型.类与应用程序不同,类的功能虽然独立,但不能独立启动,就象汽车零件那样.类机制要通过编程的方法来维护类的数据表达,值范围和操作并不是简单的,因为要限制一些操作只能让类自己来做,以免发生问题时,无人敢对其负责.类机制就是通过语言的规定性来实现一些技术,使类具有数据封装,信息屏蔽,多态等特征,起到数据类型的作用,而达到方便编程的目的.16:12:113第八章内容1.从结构到类(FromStructuretoClass)2.成员函数(MemberFunctions)3.操作符(Operators)4.再论程序结构(ProgramStrutureRestatement)5.屏蔽类的实现(ShieldClassImplementations)6.静态成员(StaticMembers)7.友元(Friends)16:12:1141.从结构到类(FromStructuretoClass)结构:单纯堆积数据空间构造的类型类:不但描述数据空间,还描述其操作的自定义类型变量:由内部数据类型或衍生的结构类型所产生的实体对象:由类产生的实体,本质上,变量也是对象,只不过粗糙一点罢了.16:12:1152.成员函数(Functions)成员函数与普通函数的区别:成员函数属于类,成员函数定义是类设计的一部分,其作用域是类作用域.而普通函数一般为全局函数成员函数的操作主体是对象,使用时通过捆绑对象来行使其职责,而普通函数被调用时没有操作主体16:12:116成员函数的内联性成员函数可以在类内,也可以在类外定义,若在类内定义,则默认为内联函数.但编译器对内联的接受自有其原则.classDate{intyear,month,day;public:voidset(inty,intm,intd){//默认内联year=y;month=m;day=d;}…};inlineboolDate::isLeapYear(){//显式内联return!(year%400)||!(year%4)&&year%100;}…16:12:117访问成员函数的方式对象方式Dated;d.set(2005,12,5);…对象指针方式Date*dp=newDate;dp-set(2005,12,5);//…deletedp;16:12:118常成员函数与函数的常量参数常成员函数对捆绑的对象,不允许写操作函数的常量参数对传递的参数,不允许写操作例如:boolDate::comp(constDate&a)const{year=2005;//error:常成员函数捆绑的对象a.year=2003;//error:常量对象returnyear==b.yaer&&month==a.month&&day==a.day;}16:12:1193.操作符(Operators)操作符定义就是函数定义,调用操作符就是调用函数,例如:Pointoperator+(constPoint&a,constPoint&b){Points;s.set(a.x+b.x,a.y+b.y);returns;}Pointp,q;p.set(3,2);q.set(1,5);Pointr=p+q;//p+q等价于operator+(p,q)一切自定义操作符都是语言中操作符的重载.操作符作用:让编译器理解人性化编程代码.从正确性上讲并不是必要的.例如,Java不允许操作符重载16:12:1110值返回返回临时表达式的值,例如:Pointoperator+(constPoint&a,constPoint&b){Points;s.set(a.x+b.x,a.y+b.y);returns;}引用返回函数将处理结果放入参数中时,如果有将返回值作连续操作的需要,便需要返回参数,即引用返回,例如:ostream&operator(ostream&o,constPoint&d){returno”(“d.x”,“d.y”)\n”;}值返回与引用返回16:12:1111成员操作符与普通操作符普通操作符:Pointoperator+(constPoint&d)const{Points;s.set(x+d.x,y+d.y);returns;}成员操作符:PointPoint::operator+(constPoint&a,constPoint&b)const{Points;s.set(a.x+b.x,a.y+b.y);returns;}p+q等价于成员操作符p.operator+(q),或者普通操作符operator(p,q)两者必居其一.16:12:11124.再论程序结构(ProgramStructureRestatement)访问控制成员函数一般为公有public公有的成员函数在类的外部可以被使用,即外界可以调用成员函数.数据成员一般为私有private私有的数据成员在外部不能被访问,即外界不能访问对象的数据分量,而只能由成员函数内部去处理.公有和私有可任意设定访问控制public和private是语言提供给程序员的功能.16:12:1113程序结构类定义作为头文件,如:point.h类的实现作为独立编译单元,如:point.cpp使用类的程序作为另一独立编译单元,如:f0809.cpp类的头文件和类的实现可以作为一个独立的资源提供给编程者.内联的成员函数定义一般放在头文件中.头文件中必须使用头文件卫士技术.16:12:1114类作用域与类定义作用域类定义作用域:从类定义结束开始,到从外面包围类定义的块结束(若类定义外无包围块,则结束于文件)使用类的程序员在类定义作用域下编程类作用域:类定义内部及成员函数定义内部实现类的程序员在类作用域下编程16:12:11155.屏蔽类的实现(ShieldClassImplementations)使用类的应用程序只需要类定义头文件编程实现类,也只需要类定义头文件,不需要使用类的程序细节确定了类定义(头文件),便可以从事两方面的编程而互不干涉.类定义成功地屏蔽了类的实现,是类机制的技术体现.16:12:11166.静态成员(StaticMembers)静态数据成员在类作用域中声明,在类定义作用域中定义(一般是在main函数启动之前定义),每个该类对象都共享.描述任何对象的共性状态.在多文件程序结构中,一般放在类的实现编译单元中.16:12:1117例如:classStudent{stringname;public:staticintnum;voidset(string&str){name=str;++num;}};intStudent::num=0;//静态数据成员初始化intmain(){Students1,s2;s1.set(Smith);s2.set(“John”);couts1.num“\n”;//可行,非标准coutStundent::num“\n”;//访问静态成员}16:12:1118静态成员函数调用时,不捆绑对象,所以,不能直接操作对象和其成员,若需访问该类对象,必须以参数传递之.静态成员函数一般设计为公有的,以访问私有静态数据成员为目的.调用方式是以类名加域操作符::后跟静态成员函数.16:12:1119例如:classStudent{staticintnum;//静态私有成员//...public://...staticvoidshowNum(){coutnum“\n”;//访问静态私有成员}};intStudent::num=0;//静态数据成员初始化intmain(){Students;s.showNum();//可行,但非标准Student::showNum();//静态成员函数调用}16:12:1120例如:矩阵乘向量函数friendVectormultiply(Matrix&m,Vector&v){Vectorr(v.size(),0);//整型向量初始值0r.set(m.szl);//直接访问私有数据成员szlfor(inti=0;im.szl;i++)for(intj=0;jm.szr;j++)r.v[i]+=m.m[i*m.szr+j]*v.v[j];returnr;}若以普通函数的身份实现,则要大量调用成员函数去访问私有数据成员,而用友元之后,可以直接访问之.16:12:1121友元的另一作用:用在无法成员化的操作符重载中例如:classPoint{//…friendostream&operator(ostream&o,constPoint&d){returno'('d.x','d.y“)\n”;}};对于Point型对象a,由于语句couta;中的第一操作数为cout,不是Point对象,所以无法在Point类中将操作符成员化,但又想长驱直入地访问Point中的私有数据成员.故用友元.