初学C++基础知识要点

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

C++程序设计主讲:李晓勇Email:lxyonghn@163.comTelphone:13819194055一、友元1、引入理由安全性----封装:类的成员函数才能访问类的私有成员,其他函数不能访问私有成员的。高效率----非封装:(1)将数据定义成公有成员----破坏隐藏性(2)友元函数----提高效率,破坏隐藏性2、友元特点(1)在类中用friend说明。位置任意,含义相同。(2)友元分:例1,在平面上计算两个点之间的距离。假设第一个点(x1,y1),第二个点(x2,y2)----普通函数作友元函数友元类普通函数成员函数友元函数classpoint//点的类{public:point(doublexx,doubleyy){x=xx;y=yy;}voidprint_xy(){cout(x,y)endl;}frienddoubledistance(point&a,point&b);//友元函数在类中说明,并非定义//可以写成:doublefrienddistance(pointa,pointb);private:doublex,y;};doubledistance(point&a,point&b)//友元函数定义{doubledx=a.x-b.x;doubledy=a.y-b.y;returnsqrt(dx*dx+dy*dy);}voidmain(){pointp1(3.0,4.0),p2(6.0,8.0);p1.print_xy();p2.print_xy();doubles=distance(p1,p2);//普通函数方式调用coutDistanceissendl;}classB;//说明classA{public:voiddisp(Bvb);protected:intx;};classB{public:B(intm){y=m;}voidfriendA::disp(Bvb){coutvb.y=vb.yendl;}protected:inty;};例2,其他类的成员函数作友元函数:voidmain(){Aa1;Bb1(100);a1.disp(b1);}//通过a1的成员函数//调用b1的数据成员//运行结果:vb.y=100友元例3,普通函数成为两个类的友员classBoat;classCar{public:Car(intj){size=j;}friendintleisure(inttime,Car&aobj,Boat&bobj);//友员函数protected:intsize;};classBoat{public:Boat(intj){size=j;}friendintleisure(inttime,Car&aobj,Boat&bobj);//友员函数protected:intsize;};intleisure(inttime,Car&aobj,Boat&bobj)//友员定义{returntime*aobj.size*bobj.size;}voidmain(){Carc1(2);Boatb1(3);inttime=4;coutleisure(time,c1,b1);}结论:•友元函数可以是一个普通的函数,也可以是其他类的成员函数,它不是本类的成员函数。•在友元函数中可以通过对象名访问类的私有和保护成员。例4,类作为友元:classy;classx{friendclassy;//类作为友元。说明位置任意public:voidset(inti){m=i;}voidset(yy1);private:intm;};classy{public:voiddisp(xp){coutp.m=p.mendl;}private:intn;friendclassx;//类作为友元。说明位置任意};voidx::set(yy1){m=y1.n;}voidmain(){xa1;ya2;a1.set(95);a2.disp(a1);}输出:p.m=95说明:当y类作为x类的友元时,y的成员函数成为x类的友元,即y的成员函数可以访问x类中任意成员。关于友元类的说明:1、友元关系是不能传递的。A类是B类的友元,B类是C类的友元,则A类与C类之间没有任何关系。2、友元关系是单方向。A类是B类的友元,则A类的成员函数可以访问B类中的所有成员;但B类中的成员函数不能访问A类中的所有成员。二、运算符重载1、什么是运算符重载?赋予已有的运算符多重含义。运算符是一种特殊的函数。例:+(4,5)=4+5函数的语义可以重新定义。重新定义的运算符又称运算符函数。2、目的:使C++代码更直观、更易读。3、哪些运算符可以重载?可以重载:算术运算符:+,-,*,/,%,++,--位操作运算符:&,|,~,^,,逻辑运算:!,&&,||比较运算:,,=,=,==,!=赋值运算:=,+=,-=,*=,/=,…其他:[],(),new,delete,不能重载:*(取内容),·(圆点),::(域运算符),?:(三目运算符),sizeof等4、运算符重载后,优先级/结合性问题重新定义的运算符,不改变原运算符的优先级和结合性,也不改变运算符的语法结构,即单目运算不变,双目运算也不变。5、重载运算符的限制(1)不能创造新的运算符(2)操作数不变;优先级不变;结合性不变;语法结构不变。(3)操作数至少有一个类的对象。6、运算符重载方式(1)重载为类的成员函数形式:类型类名::operator运算符(参数表){…}(2)重载为友元函数(但=,(),[],-不能重载。)friend类型operator运算符(参数表){…}例1,成员函数方式重载运算符将数学中的复数定义成一个类,重载加法运算符,使得两个复数直接加:如c1+c2,完成复数的实部、虚部分别相加。如不用类、不用运算符重载,则只能用结构形式,例,structcomplex{doublereal;doubleimage;}c1,c2,c3;…c3.real=c1.real+c2.real;//设c1、c2已知c3.image=c1.image+c2.image;或者,cal(c1,c2,c3)----函数方式实现用类、运算符重载方式实现classcomplex{public:complex(){real=image=0;}complex(doubler,doublei)//构造函数{real=r;image=i;}complexoperator+(constcomplex&c);//重载friendvoidprint(constcomplex&c);//输出数据private:doublereal,image;//实部,虚部};//函数的返回值必须是complexcomplexcomplex::operator+(constcomplex&c){returncomplex(real+c.real,image+c.image);}voidprint(constcomplex&c)//复数格式输出{if(c.image0)coutc.realc.imagei;elsecoutc.real'+'c.image'i';}voidmain(){complexc1(2.0,4.0),c2(4.0,-2.0),c3;c3=c1+c2;//对象赋值print(c3);//输出}运行结果:6+2i说明:(1)函数的参数可以不用const,也可以不用引用。(2)复数的减法、乘法、除法定义相似。差别??例2,用友元方式实现重载classcomplex{public:complex(){real=image=0;}complex(doubler,doublei){real=r;image=i;}friendcomplexoperator+(constcomplex&c1,constcomplex&c2);friendvoidprint(complex&c);private:doublereal,image;//实部,虚部};运算值类型//友元函数的定义complexoperator+(constcomplex&c1,constcomplex&c2){//将局部对象的值返回returncomplex(c1.real+c2.real,c1.image+c2.image);}voidprint(complex&c)//复数格式输出{if(c.image0)coutc.realc.imagei;elsecoutc.real'+'c.image'i';}voidmain(){complexc1(2.0,3.0),c2(4.0,-2.0),c3;c3=c1+c2;//对象赋值print(c3);print(complex(2,4)+complex(1,2));//两个常复数对象相加}说明:(1)函数的参数可以不用const,也可以不用引用。(2)复数的减法、乘法、除法定义相似。练习5.1:平面点重载+、-运算符,在主函数中测试。例3、前缀++,后缀++,()的重载classcounter{public:counter(){value=0;}counteroperator++();//前缀加重载counteroperator++(int);//后缀加重载counteroperator()();//圆括号重载voidprint(){coutvalueendl;}private:intvalue;};countercounter::operator()()//圆括号重载定义{return*this;}countercounter::operator++()//前缀加重载{value++;return*this;}countercounter::operator++(int)//后缀加重载{countert;t.value=value++;//普通的后缀加returnt;}voidmain(){counterc1,c2;c2=++c1;c2.print();c2=c1++;c2.print();c2=(c1);c2.print();}练习5.2:定义一个颜色类,它有红、绿、蓝三种颜色,分别用无符号整数表示,取值范围为0~255,重载运算符++(友元函数)、--(成员函数),在主函数中测试。说明:(1)函数返回值问题:countercounter::operator++()//前缀加重载{value++;return*this;}因此,有c2=c1++;如定义成void或intintcounter::operator++()//前缀加重载{value++;returnvalue;}则调用只能写成:c1++不能作右值,构成赋值语句;反而不直观。对象的值(2)对于countercounter::operator++(int)//后缀加重载{countert;t.value=value++;returnt;}---定义类,可以作右值,也可以独立表达式;否则使用不直观。---不能定义成返回引用。局部变量作用域的原因。(3)对于countercounter::operator()()//圆括号重载定义{return*this;}返回值不能为returnthis-value//类型不同returnthis//指针,类型不同(4)如没有前缀运算符重载,则前缀、后缀一样。3、类的转换运算符•对于基本类型的数据具有强制类型转换运算;•对于类的必须自己定义强制类型转换运算符。例,将RMB类的对象转换成double的强制运算符定义classRMB{public:RMB(doublevalue=0.0);operatordouble(){return(yuan+jf/100.0);}//转换运算符voiddisplay(){coutvalue=(yuan+jf/100.0)endl;}protected:unsignedin

1 / 44
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功