《运算符重载 (3)精.ppt》由会员分享,可在线阅读,更多相关《运算符重载 (3)精.ppt(121页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、运算符重载运算符重载第1页,本讲稿共121页第2页 共125页第第7章章 运算符重载运算符重载运算符重载是面向对象程序设计的重要特征。运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同的行为。C+中经重载后的运算符能直接对用户自定义的数据进行操作运算,这就是C+语言中的运算符重载所提供的功能。第2页,本讲稿共121页第3页 共125页第第7章章 运算符重载运算符重载7.1 运算符重载概述7.2 运算符重载函数的两种形式7.3几个常用运算符的重载7.4 类型转换7.5 本章小结第3页,本讲稿共121页第4页 共125页7.1 运算符重载概述运算符重载概述7.1.1
2、 运算符重载的好处7.1.2 运算符重载的规则第4页,本讲稿共121页第5页 共125页7.1.1 运算符重载的好处运算符重载的好处C+预定义的运算符只能对基本类型的数据进行操作,不能用于自定义数据类型的运算。对于用户自定义的数据类型往往需要有类似的运算操作,客观上需要定义适用用户自定义数据类型的有关运算。第5页,本讲稿共121页第6页 共125页7.1.1 运算符重载的好处运算符重载的好处定义一个简化的复数类complex:class complex public:double real,imag;complex(double r=0,double i=0)real=r;imag=i;第6页
3、,本讲稿共121页第7页 共125页7.1.1 运算符重载的好处运算符重载的好处若要把类complex的两个对象com1和com2加在一起,下面的语句是不能实现的:void main()complex com1(1.1,2.2),com2(3.3,4.4),total;total=com1+com2;/错误错误 /第7页,本讲稿共121页第8页 共125页7.1.1 运算符重载的好处运算符重载的好处若要将上述类complex的两个对象相加,只要编写一个运算符函数operator+(),如下所示:complex operator+(complex om1,complex om2)complex
4、temp;temp.real=om1.real+om2.real;temp.imag=om1.imag+om2.imag;return temp;我们就能方便地使用语句:total=com1+com2;将类complex的两个对象com1和com2相加。第8页,本讲稿共121页第9页 共125页表表7-1 运算符重载函数运算符重载函数函数功能operator+()加法operator-()减法operator*()乘法operator/()除法operator()小于.第9页,本讲稿共121页第10 共125页 7.1.2 运算符重载的规则运算符重载的规则运算符重载是针对新类型数据的实际需要,
5、对原有运算符进行适当的改造完成的。一般来讲,重载的功能应当与原有的功能相类似。只能重载C+预定义中已有的运算符,不可自己“创造”新的运算符进行重载。第10页,本讲稿共121页第11 共125页 7.1.2 运算符重载的规则运算符重载的规则以下运算符不可重载:运算符语义.成员(分量)运算符*指向成员的指针:作用域运算符?:条件运算符sizeof类型长度运算符第11页,本讲稿共121页第12 共125页 7.1.2 运算符重载的规则运算符重载的规则不能改变运算符的操作个数。不能改变运算符的原有优先级。不能改变运算符的原有结合特性。不能改变运算符对预定义类型数据的操作方式。重载运算符时,必须至少有一
6、个自定义类型的数据作为操作数。第12页,本讲稿共121页第13 共125页 7.2 运算符重载函数的两种形式运算符重载函数的两种形式运算符重载是通过创建运算符重载函数来实现的,运算符重载函数定义了重载的运算符将要进行的操作。运算符重载函数一般采用以下两种形式:成员运算符函数友元运算符函数第13页,本讲稿共121页第14 共125页 7.2 运算符重载函数的两种形式运算符重载函数的两种形式7.2.1 友元运算符函数7.2.2 成员运算符函数7.2.3 成员运算符函数与友元运算符函数的比较第14页,本讲稿共121页第15 共125页 7.2.1 友元运算符函数友元运算符函数在C+中,可以把运算符重
7、载函数定义成某个类的友元函数,称为友元运算符函数。当运算符重载为友元函数时可以自由地访问类的所有成员。运算符重载为友元函数时,运算符所需要的操作数都需要通过函数的形参来传递,在参数表中参数从左至右的顺序就是运算符操作数的顺序。第15页,本讲稿共121页第16 共125页 7.2.1 友元运算符函数友元运算符函数 友元运算符函数定义的语法形式 双目运算符重载 单目运算符重载第16页,本讲稿共121页第17 共125页 友元运算符函数定义的语法形式友元运算符函数定义的语法形式友元运算符函数的原型在类的内部声明格式如下:class X /friend 返回类型返回类型 operator运算符运算符(
8、形参表形参表);/第17页,本讲稿共121页第18 共125页 友元运算符函数定义的语法形式友元运算符函数定义的语法形式在类外定义友元运算符函数的格式如下:返回类型返回类型 operator运算符运算符(形参表形参表)函数体函数体 第18页,本讲稿共121页第19 共125页 双目运算符重载双目运算符重载当用友元函数重载双目运算符时,两个操作数都要传递给运算符函数。第19页,本讲稿共121页第20 共125页 例例7.2 用友元运算符进行复数运算用友元运算符进行复数运算两个复数a+bi和c+di进行加、减、乘、除的方法如下:加法:(a+bi)+(c+di)=(a+c)+(b+d)i减法:(a+
9、bi)-(c+di)=(a-c)+(b-d)i乘法:(a+bi)*(c+di)=(ac-bd)+(ad+bc)i除法:(a+bi)/(c+di)=(a+bi)*(c-di)/c2+d2第20页,本讲稿共121页第21 共125页 例例7.2 用友元运算符进行复数运算用友元运算符进行复数运算#include class complexpublic:complex(double r=0.0,double i=0.0);void print();friend complex operator+(complex a,complex b);friend complex operator-(complex
10、 a,complex b);friend complex operator*(complex a,complex b);friend complex operator/(complex a,complex b);private:double real;double imag;第21页,本讲稿共121页第22 共125页 例例7.2 用友元运算符进行复数运算用友元运算符进行复数运算complex:complex(double r,double i)real=r;imag=i;complex operator+(complex a,complex b)complex temp;temp.real=
11、a.real+b.real;temp.imag=a.imag+b.imag;return temp;第22页,本讲稿共121页第23 共125页 例例7.2 用友元运算符进行复数运算用友元运算符进行复数运算complex operator-(complex a,complex b)complex temp;temp.real=a.real-b.real;temp.imag=a.imag-b.imag;return temp;第23页,本讲稿共121页第24 共125页 例例7.2 用友元运算符进行复数运算用友元运算符进行复数运算complex operator*(complex a,compl
12、ex b)complex temp;temp.real=a.real*b.real-a.imag*b.imag;temp.imag=a.real*b.imag+a.imag*b.real;return temp;complex operator/(complex a,complex b)complex temp;double t;t=1/(b.real*b.real+b.imag*b.imag);temp.real=(a.real*b.real+a.imag*b.imag)*t;temp.imag=(b.real*a.imag-a.real*b.imag)*t;return temp;第24页
13、,本讲稿共121页第25 共125页 例例7.2 用友元运算符进行复数运算用友元运算符进行复数运算void complex:print()cout0)cout+;if(imag!=0)coutimagin;void main()complex A1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6;A3=A1+A2;A4=A1-A2;A5=A1*A2;A6=A1/A2;A1.print();A2.print();A3.print();A4.print();A5.print();A6.print();第25页,本讲稿共121页第26 共125页 说明说明主函数中的A3=A1+A2
14、;A4=A1-A2;A5=A1*A2;A6=A1/A2;在执行时将被解释为:A3=operator+(A1,A2);A4=operator-(A1,A2);A5=operator*(A1,A2);A6=operator/(A1,A2);第26页,本讲稿共121页第27 共125页 说明说明一一般般而而言言,如如果果在在类类X中中采采用用友友元元函函数数重重载载双双目目运运算算符符,而而aa和和bb是是类类X的的两两个个对对象象,则则以以下下两两种种函函数调用方法是等价的数调用方法是等价的:aa bb;/隐式调用隐式调用 operator(aa,bb);/显式调用显式调用第27页,本讲稿共121
15、页第28 共125页 单目运算符重载单目运算符重载用友元函数重载单目运算符时,需要一个显式的操作数。第28页,本讲稿共121页第29 共125页 例例7.3 用友元函数重载单目运算符用友元函数重载单目运算符“-”#include class ABpublic:AB(int x=0,int y=0)a=x;b=y;friend AB operator-(AB obj);void print();private:int a,b;第29页,本讲稿共121页第30 共125页 例例7.3 用友元函数重载单目运算符用友元函数重载单目运算符“-”AB operator-(AB obj)obj.a=-obj
16、.a;obj.b=-obj.b;return obj;void AB:print()couta=a b=bendl;void main()AB ob1(50,60),ob2;ob1.print();ob2=-ob1;ob2.print();第30页,本讲稿共121页第31 共125页 例例例例7.4 7.4 使用友元函数重载使用友元函数重载使用友元函数重载使用友元函数重载“+”,“-”+”,“-”时有问题时有问题时有问题时有问题#include class coordpublic:coord(int i=0,int j=0);void print();friend coord operator
17、+(coord op);private:int x,y;coord:coord(int i,int j)x=i;y=j;第31页,本讲稿共121页第32 共125页 例例例例7.4 7.4 使用友元函数重载使用友元函数重载使用友元函数重载使用友元函数重载“+”,“-”+”,“-”时有问题时有问题时有问题时有问题void coord:print()coutx:x,y:yendl;coord operator+(coord op)+op.x;+op.y;return op;void main()coord ob(10,20);ob.print();operator+(ob);ob.print();
18、+ob;ob.print();第32页,本讲稿共121页第33 共125页 例例7.5 使用引用参数重写例使用引用参数重写例7.4#include class coordpublic:coord(int i=0,int j=0);void print();friend coord operator+(coord&op);private:int x,y;coord:coord(int i,int j)x=i;y=j;第33页,本讲稿共121页第34 共125页 例例7.5 使用引用参数重写例使用引用参数重写例7.4void coord:print()coutx:x,y:y用指针访问对象成员第38
19、页,本讲稿共121页第39 共125页 7.2.2 成员运算符函数成员运算符函数在C+中,可以把运算符函数定义成某个类的成员函数,称为成员运算符函数。运算符重载为成员函数后,可以自由访问本类的任何成员。对于双目运算符,其左操作数一定是对象本身,由this指针给出,另一个操作数则需要通过运算符重载函数的参数表进行传递。对于单目运算符,对象的this指针直接给出操作数,因此不再需要任何其他参数。第39页,本讲稿共121页第40 共125页 7.2.2 成员运算符函数成员运算符函数 成员运算符函数定义的语法形式 双目运算符重载 单目运算符重载第40页,本讲稿共121页第41 共125页 成员运算符函
20、数定义的语法形式成员运算符函数定义的语法形式成员运算符函数的原型在类的内部声明格式如下:class X /返回类型返回类型 operator运算符运算符(形参表形参表);/第41页,本讲稿共121页第42 共125页 成员运算符函数定义的语法形式成员运算符函数定义的语法形式在类外定义成员运算符函数的格式如下:返回类型返回类型 X:operator运算符运算符(形参表形参表)函数体函数体第42页,本讲稿共121页第43 共125页 成员运算符函数定义的语法形式成员运算符函数定义的语法形式在成员运算符函数的形参表中,若运算符是单目的,则参数表为空;若运算符是双目的,则参数表中有一个参数。第43页,
21、本讲稿共121页第44 共125页 双目运算符重载双目运算符重载对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。第44页,本讲稿共121页第45 共125页 例例7.6 采用成员运算符函数改写例采用成员运算符函数改写例7.2#include class complexpublic:complex(double r=0.0,double i=0.0);void print();complex operator+(complex c);complex operator-(complex c);
22、complex operator*(complex c);complex operator/(complex c);private:double real;double imag;第45页,本讲稿共121页第46 共125页 例例7.6 采用成员运算符函数改写例采用成员运算符函数改写例7.2 complex:complex(double r,double i)real=r;imag=i;complex complex:operator+(complex c)return complex(real+c.real,imag+c.imag);complex complex:operator-(com
23、plex c)return complex(real-c.real,imag-c.imag);第46页,本讲稿共121页第47 共125页 例例7.6 采用成员运算符函数改写例采用成员运算符函数改写例7.2 complex complex:operator*(complex c)return complex(real*c.real-imag*c.imag,real*c.imag+imag*c.real);complex complex:operator/(complex c)complex t1(c.real,-c.imag),t2(1/(c.real*c.real+c.imag*c.imag
24、);return(*this)*t1*t2;void complex:print()cout0)cout+;if(imag!=0)coutimagin;第47页,本讲稿共121页第48 共125页 例例7.6 采用成员运算符函数改写例采用成员运算符函数改写例7.2 void main()complex A1(2.3,4.6),A2(3.6,2.8),A3,A4,A5,A6;A3=A1+A2;A4=A1-A2;A5=A1*A2;A6=A1/A2;A1.print();A2.print();A3.print();A4.print();A5.print();A6.print();第48页,本讲稿共1
25、21页第49 共125页 说明说明主函数中的A3=A1+A2;A4=A1-A2;A5=A1*A2;A6=A1/A2;在执行时将被解释为:A3=A1.operator+(A2);A4=A1.operator-(A2);A5=A1.operator*(A2);A6=A1.operator/(A2);第49页,本讲稿共121页第50 共125页 说明说明一一般般而而言言,如如果果在在类类X中中采采用用成成员员函函数数重重载载双双目目运运算算符符,成成员员运运算算符符函函数数operator 所所需需的的一一个个操操作作数数由由对对象象aa通通过过this指指针针隐隐含含地地传传递递,它它的的另另一一
26、个个操操作作数数bb在在参参数数表表中中显显示示,aa和和bb是是类类X的的两两个个对对象象,则以下两种函数调用方法是等价的则以下两种函数调用方法是等价的:aa bb;/隐式调用隐式调用 aa.operator(bb);/显式调用显式调用 第50页,本讲稿共121页第51 共125页 单目运算符重载单目运算符重载对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。第51页,本讲稿共121页第52 共125页 例例7.7 重载单目运算符重载单目运算符“+”#include class coordpublic:coord(int i=0,int j=0);voi
27、d print();coord operator+();private:int x,y;coord:coord(int i,int j)x=i;y=j;第52页,本讲稿共121页第53 共125页 例例7.7 重载单目运算符重载单目运算符“+”void coord:print()coutx:x,y:yendl;coord coord:operator+()+x;+y;return*this;void main()coord ob(10,20);ob.print();+ob;ob.print();ob.operator+();ob.print();第53页,本讲稿共121页第54 共125页 说
28、明说明一一般般而而言言,采采用用成成员员函函数数重重载载单单目目运运算算符符时时,以以下下两两种种方方法法是是等价的等价的:aa;/隐式调用隐式调用 aa.operator();/显式调用显式调用 成成员员运运算算符符函函数数operator 所所需需的的一一个个操操作作数数由由对对象象aa通通过过this指指针针隐隐含含地地传传递递。因因此此,在在它它的的参参数数表表中中没没有有参参数数。注注意意:关关于于成成员函数重载单目运算符后缀方式的表示方法,将在员函数重载单目运算符后缀方式的表示方法,将在7.3.1节介绍。节介绍。第54页,本讲稿共121页第55 共125页 7.2.3 7.2.3
29、成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较 对双目运算符而言,成员运算符函数带有一个参数,而友元运算符函数带有两个参数;对单目运算符而言,成员运算符函数不带参数,而友元运算符函数带一个参数。双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但有一种情况,必须使用友元函数。第55页,本讲稿共121页第56 共125页 7.2.3 7.2.3 成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较例如
30、,在类AB中,用成员运算符函数重载“+”运算符:AB:operator+(int x)AB temp;temp.a=a+x;temp.b=b+x;return temp;第56页,本讲稿共121页第57 共125页 7.2.3 7.2.3 成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较成员运算符函数与友元运算符函数的比较若类AB的对象ob要做赋值运算和加法运算,以下是一条正确的语句:ob=ob+200;然而,下一条语句就不能工作了:ob=200+ob;用友元方式来重载“+”(或其他双目运算符)就能消除这种问题,从而使得内部数据类型能
31、出现在运算符左边。第57页,本讲稿共121页第58 共125页 例例例例7.8 内部数据类型能出现在运算符的左边内部数据类型能出现在运算符的左边内部数据类型能出现在运算符的左边内部数据类型能出现在运算符的左边#include class ABpublic:AB(int x=0,int y=0);friend AB operator+(AB ob,int x);friend AB operator+(int x,AB ob);void show();private:int a,b;AB:AB(int x,int y)a=x;b=y;第58页,本讲稿共121页第59 共125页 例例7.8 内部数
32、据类型能出现在运算符的左边内部数据类型能出现在运算符的左边内部数据类型能出现在运算符的左边内部数据类型能出现在运算符的左边AB operator+(AB ob,int x)return AB(ob.a+x,ob.b+x);AB operator+(int x,AB ob)return AB(x+ob.a,x+ob.b);void AB:show()couta=a b=b”只能作为成员函数。对于运算符“+=、-=、*=、/=、&=、!=、=、%=、=、=”,建议重载为成员函数。对于其他运算符,建议重载为友元函数。第62页,本讲稿共121页第63 共120页 7.3几个常用运算符的重载几个常用运算
33、符的重载7.3.1 单目运算符“+”和“-”的重载7.3.2 赋值运算符“=”的重载7.3.3 插入运算符“”重载第63页,本讲稿共121页第64 共120页 7.3.1 单目运算符单目运算符“+”和和“-”的重载的重载在C+中,可以通过在运算符函数参数表中是否插入关键字int来区分前缀和后缀这两种方式。对于前缀方式对于前缀方式+ob,可以用运算符函数重载为可以用运算符函数重载为 ob.operator+();/成员函数重载成员函数重载 或或 operator+(X&ob);/友元函数重载友元函数重载,其中其中ob为类为类X对象的引用对象的引用第64页,本讲稿共121页第65 共120页 7.
34、3.1 单目运算符单目运算符“+”和和“-”的重载的重载对于后缀方式对于后缀方式ob+,可以用运算符函数重载为可以用运算符函数重载为 ob.operator+(int);/成员函数重载成员函数重载 或或 operator+(X&ob,int);/友元函数重载友元函数重载在调用后缀方式的函数时在调用后缀方式的函数时,参数参数int一般被传递给一般被传递给值值0。第65页,本讲稿共121页第66 共120页 例例7.9 “+”和和“-”重载举例重载举例#include class three_dpublic:three_d()x=0;y=0;z=0;three_d(int i,int j,int
35、k)x=i;y=j;z=k;void show(int&i,int&j,int&k)i=x;j=y;k=z;three_d operator+();three_d operator+(int);friend three_d operator-(three_d&);friend three_d operator-(three_d&,int);private:int x,y,z;第66页,本讲稿共121页第67 共120页 例例7.9“+”和和“-”重载举例重载举例three_d three_d:operator+()+x;+y;+z;return*this;three_d three_d:ope
36、rator+(int)x+;y+;z+;return*this;three_d operator-(three_d&op)-op.x;-op.y;-op.z;return op;three_d operator-(three_d&op,int)op.x-;op.y-;op.z-;return op;第67页,本讲稿共121页第68 共120页 例例7.9“+”和和“-”重载举例重载举例 void main()three_d ob1(10,10,10),ob2(20,20,20);int x,y,z;ob1.show(x,y,z);cout(ob1)x:x,y:y,z:zendl;ob1+;/o
37、perator+(int)ob1.show(x,y,z);cout(ob1+)x:x,y:y,z:zendl;+ob1;/operator+()ob1.show(x,y,z);cout(+ob1)x:x,y:y,z:zendl;cout-endl;第68页,本讲稿共121页第69 共125页 例例7.9“+”和和“-”重载举例重载举例ob2.show(x,y,z);cout(ob2)x:x,y:y,z:zendl;operator-(ob2);/-ob2;ob2.show(x,y,z);cout(-ob2)x:x,y:y,z:zendl;operator-(ob2,0);/ob2-;ob2.s
38、how(x,y,z);cout(ob2-)x:x,y:y,z:zendl;第69页,本讲稿共121页第70 共120页 例例7.10 以前缀和后缀方式重载以前缀和后缀方式重载“+”#include class Numberpublic:Number(int i)num=i;int operator+()num+;return num;int operator+(int)int i=num;num+;return i;void print()coutnumendl;private:int num;;;第70页,本讲稿共121页第71 共120页 例例7.10 以前缀和后缀方式重载以前缀和后缀方式
39、重载“+”void main()Number n(100);int i=+n;couti=iendl;i=n+;couti=iendl;n.print();第71页,本讲稿共121页第72 共120页 说明说明运算符“+”和“-”都对单值操作数产生影响,因此用成员运算符函数重载自增运算符“+”与自减运算符“-”的成员函数通常返回指针this。由于友元运算符函数没有this指针,所以不能引用this指针所指的对象。使用友元运算符函数重载自增运算符“+”或自减运算符“-”时,应采用引用参数传递数据。第72页,本讲稿共121页第73 共120页 说明说明前缀方式和后缀方式的函数内部的语句可以相同,也
40、可以不同,取决于编程者的考虑。第73页,本讲稿共121页第74 共120页 7.3.2 赋值运算符赋值运算符“=”的重载的重载对任一类X,如果没有用户自定义的赋值运算符函数,那么系统自动地为其生成一个缺省的赋值运算符函数,定义为类X中的成员到成员的赋值,例如:X&X:operator=(const X&source)/成员间赋值成员间赋值 第74页,本讲稿共121页第75 共125页 7.3.2 赋值运算符赋值运算符“=”的重载的重载若obj1和obj2是类X的两个对象,obj2已被创建,则编译程序遇到如下语句:obj1=obj2;就调用缺省的赋值运算符函数,将对象obj2的数据成员的值逐个赋
41、给对象obj1的对应数据成员中。第75页,本讲稿共121页第76 共125页 7.3.2 赋值运算符赋值运算符“=”的重载的重载通常,缺省的赋值运算符函数是能够胜任工作的。但是,对于许多重要的实用类来说,仅有缺省的赋值运算符函数还是不够的,还需要用户根据实际需要自己对赋值运算符进行重载。指针悬挂问题 重载赋值运算符解决指针悬挂问题第76页,本讲稿共121页第77 共125页 指针悬挂问题指针悬挂问题在某些特殊情况下,如类中有指针类型时,使用缺省的赋值运算符函数会产生错误。请看下面的例子:第77页,本讲稿共121页第78 共125页 例例例例7.11 7.11 使用缺省的赋值运算符函数会产生错误
42、使用缺省的赋值运算符函数会产生错误使用缺省的赋值运算符函数会产生错误使用缺省的赋值运算符函数会产生错误#include#include class string public:string(char*s)ptr=new charstrlen(s)+1;strcpy(ptr,s);string()delete ptr;void print()coutptrendl;private:char*ptr;;第78页,本讲稿共121页第79 共125页 例例例例7.11 7.11 使用缺省的赋值运算符函数会产生错误使用缺省的赋值运算符函数会产生错误使用缺省的赋值运算符函数会产生错误使用缺省的赋值运算符函
43、数会产生错误 void main()string p1(book);string p2(pen);p1=p2;coutp2:;p2.print();coutp1:;p1.print();第79页,本讲稿共121页第80 共125页 重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题为了解决上述使用缺省的赋值运算符所遇到的指针悬挂问题,必须重载赋值运算符,使得对目标对象数据成员指针的赋值,是把原对象指针ptr所指向的内容传递给它,而不是简单地传递指针值。第80页,本讲稿共121页第81 共125页 例例例例 7.12 7.12 重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问
44、题重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题#include#include class string public:string(char*s)ptr=new charstrlen(s)+1;strcpy(ptr,s);string()delete ptr;void print()coutptrendl;string&operator=(const string&);/声明赋值运算符重载函数声明赋值运算符重载函数 private:char*ptr;第81页,本讲稿共121页第82 共125页 例例例例 7.12 7.12 重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针
45、悬挂问题重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题string&string:operator=(const string&s)/定义赋值运算符重载函数定义赋值运算符重载函数 if(this=&s)return*this;/防止防止s=s的赋值的赋值 delete ptr;/释放掉原区域释放掉原区域 ptr=new charstrlen(s.ptr)+1;/分配新区域分配新区域 strcpy(ptr,s.ptr);/字符串拷贝字符串拷贝 return*this;第82页,本讲稿共121页第83 共125页 例例例例 7.12 7.12 重载赋值运算符解决指针悬挂问题重载赋值运
46、算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题重载赋值运算符解决指针悬挂问题void main()string p1(book);string p2(pen);p1=p2;coutp2:;p2.print();coutp1:;p1.print();第83页,本讲稿共121页第84 共125页 说明说明类的赋值运算符“=”只能重载为成员函数,而不能把它重载为友元函数。类的赋值运算符“=”可以被重载,但重载了的运算符函数operator=()不能被继承。第84页,本讲稿共121页第85 共125页 7.3.3 7.3.3 插入运算符插入运算符插入运算符插入运算符“”重载重载重载重载把输出与输入
47、看作数据的流动过程,因此把输出数据与输入数据称为输出流与输入流,对其操作称为插入与提取。预定义插入符 插入运算符“”重载 第85页,本讲稿共121页第86 共125页 预定义插入符预定义插入符 系统预定义有一个ostream类,用于管理数据的输出,cout就是它的一个对象。表达式 couti;将被编译器解释为cout.operator(i);其中,i是传递给这个对象并启动其方法函数operator的一个消息。称为插入运算符。第86页,本讲稿共121页第87 共125页 预定义插入符预定义插入符系统提供的重载函数operator()原型为:ostream&ostream:operator(typ
48、e&obj);第87页,本讲稿共121页第88 共125页 预定义插入符预定义插入符系统预定义的type为以下类型之一:char、int、short、long或unsigned、signed类型;float、double、long double类型;char*或void*类型。第88页,本讲稿共121页第89 共125页 重载函数重载函数operator()原型说明原型说明函数operator()是类ostream的重载方法函数,其参数分别为系统预定义的上述各type类型。这个函数返回一个ostream的引用类型,系统预定义的流cout,cerr,clog是ostream类的对象。对于下面的提
49、取表达式 coutijk将被解释为 (cout.operator(i).operator(j).operator(k)第89页,本讲稿共121页第90 共125页 重载函数重载函数operator()原型说明原型说明当type为char*时,用于在流中插入一个字符串;当type为void*时用于在流中插入一个指针的值(地址),编译器将按所调用的重载插入函数的参数类型与void*匹配。如下例中,分别输出字符串的值和其首地址。第90页,本讲稿共121页第91 共125页 例例1 char型指针值的输出型指针值的输出#include void main()const char*s=Hello,Vis
50、ual C+!;coutsendl;cout(void*)sendl;第91页,本讲稿共121页第92 共125页 重载函数重载函数operator()原型说明原型说明应当注意插入表达式中的副作用。这种副作用来自于以下两个方面:程序员对语法理解的错误 编译器执行的随意性第92页,本讲稿共121页第93 共125页 程序员对语法理解的错误程序员对语法理解的错误如表达式couta?1:0;就是对优先级别错误理解的结果。正确的写法应是:cout(a?1:0);第93页,本讲稿共121页第94 共125页 例例 2 优先级导致的错误优先级导致的错误#include int fun()coutSorry