第8章运算符重载(精品).ppt

上传人:hyn****60 文档编号:71618984 上传时间:2023-02-03 格式:PPT 页数:50 大小:189.50KB
返回 下载 相关 举报
第8章运算符重载(精品).ppt_第1页
第1页 / 共50页
第8章运算符重载(精品).ppt_第2页
第2页 / 共50页
点击查看更多>>
资源描述

《第8章运算符重载(精品).ppt》由会员分享,可在线阅读,更多相关《第8章运算符重载(精品).ppt(50页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、第8章 运算符重载目 录81 运算符重载概述运算符重载概述82 单目运算符重载单目运算符重载83 双目运算符重载双目运算符重载84 比较运算符重载比较运算符重载85 赋值运算符重载赋值运算符重载86 下标运算符重载下标运算符重载87 运算符运算符new与与delete重载重载(自学)(自学)88 逗号运算符重载逗号运算符重载(自学)(自学)89 类型转换运算符重载类型转换运算符重载810 运算符重载应用实例运算符重载应用实例问题引入:#include class complexprivate:double real;double imag;public:complex(double r=0.0

2、,double i=0.0)real=r;imag=i;void display()coutreal“+”image“i”endl;void main()int ia1,ib=2,ic;ic=ia+ib;complex a(10,20),b(5,8),c;c=a+b?C+C+预定义的运算符的操作对象只能是基本数据类预定义的运算符的操作对象只能是基本数据类型,那么用户自定义类型呢?型,那么用户自定义类型呢?运算符重载运算符重载!8.1 运算符重载概述运算符重载概述背景背景c+中预定义的运算符的操作对象只能是基本数据类型,而用户自定义类型(比如类)也需要有类似的运算操作能否对运算符重新定义,赋予已

3、有符号以新的功能?运算符重载运算符重载“借用”已有的运算符,对其赋予多重含义,对自定义的类对象实现自定义的新功能!同一个运算符作用于不同类型数据导致不同的行为运算符重载实质就是函数重载!运算符重载实质就是函数重载!运算符重载的规则运算符重载的规则(1)只能重载已有的只能重载已有的C+运算符运算符,不可自创新的运算符不可自创新的运算符!C+中的运算符除少数几个,全部可以重载,(表8.2),(2)重载后运算符的重载后运算符的优先级和结合性优先级和结合性都都不变不变。(3)重载的功能应当与原有功能相类似重载的功能应当与原有功能相类似 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。

4、一般来讲,重载的功能应当与原有功能相类似不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。表表8.2 C+中可以重载的运算符中可以重载的运算符!+-*&/%=!=|&+=-=*=/=%=&=|=,-*-()=+-newdelete表表8.1 8.1 C+C+中可以重载的运算符中可以重载的运算符表表82 C+中不能重载的运算符中不能重载的运算符.*:?:complex a(2,3),b(4,5),c;c=a+b;c=add(a,b);/complex add(complex a,complex b).c=a.add(b);/complex complex:add(comple

5、x b).+(a,b)complex operator+(complex a,complex b);complex operator+(complex b);注意:注意:运算符重载的实质就是函数重载。运算符重载的实质就是函数重载。在实现过程中,首先把指定的表达式转化为对运算符函数的调在实现过程中,首先把指定的表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用的函数,这个过程在编译过程中完成的。来确定需要调用的函数,这个过程在编译过程中完成的。自定义类中运算符重载的形式自定义类中运算符重载的形式(

6、2种种)重载为类的公有成员函数重载为类的公有成员函数 operator();重载为类的友元函数重载为类的友元函数friend operator();二者区别参数个数不同!成员函数方式重载:参数个数比原来运算数少一个(后缀+、-除外)就是缺省的this指针友元函数方式重载:参数个数与原运算数个数相同,且至少有一个参数是说明该友元的类或是该类的引用单目运算符最好重载为类的成员函数双目运算符则最好重载为类的友元函数!成员方式重载成员方式重载vs友元方式重载友元方式重载成员方式重载:成员方式重载:因每个成员函数总是将当前调用对象(this指针)作为该成员函数隐含的第一个参数运算符的第一个运算对象所以若

7、某个对象使用重载了的成员函数,自身的数据可以直接访问,就不需要再放在参数表中进行传递,少了的运算数就是该对象本身(this指针)友元方式重载:友元方式重载:而友元函数中没有this指针,所以友元函数对某个对象的数据进行操作时,就必须通过该对象的名称来实现,因此使用到的所有运算分量都要进行传递 运算数的个数就不会有变化。一般来讲,单目运算符最好重载为成员函数,而双目一般来讲,单目运算符最好重载为成员函数,而双目运算符则最好重载为友元函数运算符则最好重载为友元函数目录8.2 单目运算符重载+/-#include class Sampleprivate:int n;public:Sample(int

8、 i=0):n(i)void display()cout n=n endl;void operator+()+n;/+运算符重载运算符重载;void main()Sample a(5);+a;a.display();a.operator+();n=6在在C+C+中,单目运算符有中,单目运算符有+和和 例8.1+/-前缀、后缀重载前缀、后缀重载“+”、“-”运算符有前缀和后缀两种形运算符有前缀和后缀两种形式式“+”和和“-”重载运算符也有前缀和后缀重载运算符也有前缀和后缀两种两种以以“+”重载运算符为例重载运算符为例 operator+();/前缀运算前缀运算 operator+(int);/后

9、缀运算后缀运算 使用使用前缀运算符 +;后缀运算符 +;例8.1增加后缀+重载 例8.2#include class Sampleprivate:int n;public:Sample(int i):n(i)void operator+()+n;/前缀运算符重载前缀运算符重载void operator+(int)n+=2;/后缀运算符重载后缀运算符重载void display()cout n=n endl;void main()Sample a(5),b(5);a+;/调用后缀运算符重载调用后缀运算符重载+b;/调用前缀运算符重载调用前缀运算符重载a.display();b.display()

10、;n=7n=6#include class Sampleprivate:int n;public:Sample(int i):n(i)void operator+()/前缀运算符前缀运算符 +n;void operator+(int)/后缀运算符后缀运算符 n+=2;void display()cout n=n endl;例8.2重载函数带返回值 例8.3n=7n=6重载运算符也可以具有返回值,其使用格式如同一般的成员函数一样。重载运算符也可以具有返回值,其使用格式如同一般的成员函数一样。int operator+()/前缀运算符前缀运算符 +n;return n;int operator+(

11、int)/后缀运算符后缀运算符 n+=2;return n;void main()Sample a(5),b(5);a+;/调用后缀运算符重载调用后缀运算符重载 +b;/调用前缀运算符重载调用前缀运算符重载 a.display();b.display();cout“n=”a+endl;cout“n=”+bendl;int i;Sample c(0);i=+a;/对!对!+a返回值是返回值是int/c=+a;/错!错!C是是sample类型类型#include class Sampleprivate:int n;public:Sample(int i):n(i)Sample operator+(

12、)/前缀运算符前缀运算符 +n;return Sample(n);/return*this Sample operator+(int)/后缀运算符后缀运算符 return Sample(n+);void display()cout n endl;改进例8.3更改返回值为对象void main()Sample a(5),b(5)c(0),d(0);c=a+;/对!对!C是是sample/类型类型+a/返回值是返回值是int d=+b;coutc=;c.display();couta=;a.display();coutd=;d.display();coutb=;b.display();c=5a=6

13、d=6b=6目录83 双目运算符重载双目运算符重载双目运算符重载为类的成员函数双目运算符重载为类的成员函数双目运算符重载为类的友元函数双目运算符重载为类的友元函数(1)双目运算符重载为类的成员函双目运算符重载为类的成员函数数双目运算符,运算符需要的两个运算数双目运算符,运算符需要的两个运算数B oprd1 B oprd2第一个运算数为类的对象本身(调用此成员函数的对象)第二个运算数通过参数传递class A operator B(oprd2);A a,b;a B b;a.operator B(b);例:例:a+b;a.operator+(b);#include class Vector/向量向

14、量(x,y)private:int x,y;public:Vector()x=0;y=0;Vector(int x1,int y1)x=x1;y=y1;void display()cout (x ,y )x+v.x;tmp.y=y+v.y;return tmp;/返回返回tmp对象对象Vector Vector:operator-(Vector v)Vector tmp;/定义一个定义一个tmp对象对象tmp.x=x-v.x;tmp.y=y-v.y;return tmp;/返回返回tmp对象对象 例8.4 结果:结果:v1=(6,8)v2=(3,6)v1+v2=(9,14)v1-v2=(3,2

15、)void main()Vector v1(6,8),v2(3,6),v3,v4;cout v1=;v1.display();cout v2=;v2.display();v3=v1+v2;/v3=v1.operator+(v2);cout v1+v2=;v3.display();v4=v1-v2;/v4=v1.operator-(v2);cout v1-v2=;v4.display();(2)双目运算符重载为类的友元函数双目运算符重载为类的友元函数例8.5运算符所需的运算数都要通过函数的形参表来传递,参数表中形参从左到右的顺序就是运算符运算数的顺序。#include class Vectorp

16、rivate:int x,y;public:Vector()x=0;y=0;Vector(int x1,int y1)x=x1;y=y1;void display()cout (x ,y )、”的运算符重载。任意给3个Line类的对象,都可以判断是否有两个相加大于第3个。#include class Lineint len;public:Line(int n):len(n)Line operator+(Line l)/+运算符重载运算符重载 int x=len+l.len;return Line(x);/无名临时对象无名临时对象 bool operator(Line l)/“运算符重载运算符重

17、载 return(lenl.len)?true:false;Line temp(x);return temp;void main()Line a(10),b(5),c(14);if(a+bc&a+cb&b+ca)cout 能够构成一个三角形能够构成一个三角形 endl;elsecout 不能够构成一个三角形不能够构成一个三角形 c)运算过程为运算过程为(a.operator+(b).operator(c)目录85 赋值运算符重载赋值运算符重载在在C+中有两种类型的赋值运算符:中有两种类型的赋值运算符:“”:直接赋值的运算符。“+=”等:先计算后赋值的复合赋值运算符851 运算符“=”的重载赋值

18、运算符“=”的原有含义是将赋值号右边表达式的结果拷贝给赋值号左边的变量。为了保证同类对象之间能够进行赋值操作,每个类应定义赋值操作(重载运算符)。如果程序中没有定义赋值操作,则c编译器自动生成,实现将赋值号右边对象的数据成员依次拷贝到赋值号左边对象的数据成员中。(浅拷贝)浅拷贝带来的悬挂指针问题浅拷贝带来的悬挂指针问题class Mprivate:int*p;public:M(int i);M();void print();M:M(int i)p=new int(i);M:M()delete p;编译器自动生成:编译器自动生成:M:M(const M&m):p(m.p)M&M:operator

19、=(const M&m)p=m.p;return*this;5aM a(5),b(a);b5aM a(5),b(7);7b b=a5a7b自己定义(深拷贝)自己定义(深拷贝)M:M(const M&m)p=new int;*p=*m.p;M&M:operator=(const M&m)*p=*(m.p);return*this;5aM a(5),b(7);7b b=a7a7b5aM a(5),b(a);b5例8.8#include#include class samplepublic:sample(char*pn)p=new charstrlen(pn)+1;strcpy(p,pn);samp

20、le(const sample&s);sample()delete p;void disp()coutpendl;sample&operator=(const sample&s);private:char*p;sample:sample(const sample&s)p=new charstrlen(s.p)+1;strcpy(p,s.p);sample&sample:operator=(const sample&s)delete p;p=new charstrlen(s.p)+1;strcpy(p,s.p);return*this;svoid main()sample inst1(first

21、 object);sample inst2(second object);cout 执行语句之前执行语句之前:endl;cout inst1*p=;inst1.disp();cout inst2*p=;inst2.disp();cout 执行语句之后执行语句之后:endl;inst2=inst1;cout inst1*p=;inst1.disp();cout inst2*p=;inst2.disp();执行赋值语句之前:instl*p=firstobject inst2*p=secondobject执行赋值语句之后:instl*p=firstobjectinst2*p=firstobjecti

22、nst3=inst2=inst1;目录(略)8.5.2 运算符“+=”和“-=”的重载 对于标准数据类型,“+=”和“-=”的作用是将一个数据与另一个数据进行加法或减法运算后再将结果回送给赋值号左边的变量中。a+=ba=a+b对对 例例8 877进行修改进行修改#include class Vectorprivate:int x,y;public:Vector()x(0),y(0);Vector(int x1,int y1)x=x1;y=y1;void display()cout (x ,y )endl;Vector operator-=(Vector v);friend Vector&ope

23、rator+=(Vector&v1,Vector v2);/修改书上修改书上Vector&Vector:operator-=(Vector v)/成员函数方式成员函数方式x-=v.x;y-=v.y;return*this;Vector&operator+=(Vector&v1,Vector v2)/友元方式友元方式v1.x+=v2.x;v1.y+=v2.y;return v1;void main()Vector v1(6,8),v2(3,6),v3,v4;cout v1=;v1.display();cout v2=;v2.display();v3=v1+=v2;/v3=operator+=(v

24、1,v2);cout v1+=v2 后后,v1=;v1.display();v4=v1-=v2;/v4=v1.operator-=(v2);cout v1-v2 后后,v1=;v1.display();结果:结果:v1=(6,8)v2=(3,6)v1+=v2后后,v1=(9,14)v1-v2后,后,v1=(6,8)目录8.6 下标运算符重载下标运算符重载 下标运算符下标运算符“”通常用于取数组的某个元通常用于取数组的某个元素素下标运算符重载下标运算符重载可实现数组下标越界检测等。只能作为类的成员函数,不能作为类的友元函数例例8.9#include#include class wordspriv

25、ate:int len;char*str;public:words(char*s)str=new charstrlen(s)+1;strcpy(str,s);len=strlen(s);words()delete s;void disp()coutstrlen-1)cout 数组下标超界数组下标超界;return 0;/返回一个特殊字符返回一个特殊字符elsereturn*(str+n);void main()words word(This is C+Book);word.disp();cout “位置位置0:;cout word0 endl;/显示显示Tcout 位置位置15:;cout w

26、ord15 endl;/显示显示Kcout 位置位置25:;cout word25 endl;/显示显示超界超界This is C+Book位置 0:T位置 15:K位置 25:数组下标超界目录(略略)8.7 运算符运算符new与与delete重载重载(自自学学)C+提供提供new与与delete运算符用于内存管理运算符用于内存管理.大多数情况下,它们是非常有效的。但有些大多数情况下,它们是非常有效的。但有些情况下我们需要自己管理内存,以克服情况下我们需要自己管理内存,以克服new与与delete的不足。这就要重载运算符的不足。这就要重载运算符new与与delete,使其按照要求完成对内存的管

27、理。使其按照要求完成对内存的管理。例例8.10#include#include class Rectpublic:Rect(int l,int w)length=l;width=w;void disp()cout 面积面积:length*width endl;void*operator new(size_t size)void operator delete(void*p)private:int length,width;void*Rect:operator new(size_t size)cout 重载重载new运算符分配内存运算符分配内存 endl;return malloc(size);

28、void Rect:operator delete(void*p)free(p);cout 重载重载delete运算符释放内存运算符释放内存 disp();delete p;重载new运算符分配内存 面积:45 重载delete运算符释放内存 程序的程序的main()函数中使用的函数中使用的new和和delete运算符都调用相应的重载运运算符都调用相应的重载运算符成员函数,分别用于内存的分配算符成员函数,分别用于内存的分配和释放。和释放。目录(略)8.8 逗号运算符重载(自学)逗号运算符是双目运算符,和其他运算符逗号运算符是双目运算符,和其他运算符一样,我们也可以通过重载逗号运算符来完成一样,

29、我们也可以通过重载逗号运算符来完成期望完成的工作。期望完成的工作。逗号运算符构成的表达式为逗号运算符构成的表达式为“左运算数,右运算数左运算数,右运算数”该表达式返回右运算数的值。如果用类的该表达式返回右运算数的值。如果用类的成员函数来重载逗号运算符,则只带一个右运成员函数来重载逗号运算符,则只带一个右运算数,而左运算数由指针算数,而左运算数由指针this提供。提供。例例811 给出以下程序的执行结果:给出以下程序的执行结果:#include#include class Pointpublic:Point()x=0;y=0;Point(int x1,int y1)x=x1;y=y1;void

30、disp()cout “(”x“,”y“)”endl;Point operator,(Point r);Point operator+(Point r);private:int x,y;Point Point:operator+(Point r)Point temp;temp.x=x+r.x;temp.y=y+r.y;return temp;Point Point:operator,(Point r)Point temp;temp.x=r.x;temp.y=r.y;return temp;void main()Point r1(3,3),r2(5,8),r3(2,4);r1.disp();r2

31、.disp();r3.disp();r1=(r1,r2+r3,r3);r1.disp();(3,3)(5,8)(2,4)(2,4)计算计算r1=(r1,r2+r3,r3)先计算先计算(r1,r2+r3),),返回返回r2+r3的的结果,将其与结果,将其与r3进行逗进行逗号运算,返回号运算,返回r3的结果的结果目录89 类型转换运算符重载类型转换运算符重载C+中提供了标准类型的相互转换中提供了标准类型的相互转换int n=(int)1.87;/则则n=1。类型转换运算符重载,格式如下:类型转换运算符重载,格式如下:operator();注:与以前的重载运算符函数不同的是,注:与以前的重载运算符函

32、数不同的是,类型转换运算符重载函数没有返回类型(因为类型名就代表了它的返回类型)没有任何参数。在调用过程中要带一个对象实参。例例812 Length类将用户输入的类将用户输入的meter(以米为单以米为单位位)值转换成以千米为单位的长度:值转换成以千米为单位的长度:#include class Lengthprivate:int meter;public:Length(int m)meter=m;operator float()return(1.0*meter/1000);void main()Length a(1500);float m=float(a);/带一个对象实参进行调用带一个对象实

33、参进行调用coutm=m千米千米endl;m=1.5千米千米例例813#include#include class Stringspublic:Strings()strcpy(str,”);Strings(char st)strcpy(str,st);void disp()coutstrendl;operator char*()return str;private:char strSIZE;static const int SIZE=80;void main()Strings ps1(Sun rise,sun set.);ps1.disp();char*ps2;ps2=(char*)ps1;/

34、调用调用(char*)运算符重载函数运算符重载函数coutps2endl;Sun rise,sun set.Sun rise,sun set.实际上,类型转换运算符将对象转换成类型实际上,类型转换运算符将对象转换成类型名规定的类型。名规定的类型。转换时的形式就像强制转换一样。转换时的形式就像强制转换一样。如果没有转换运算符定义,直接用强制转换如果没有转换运算符定义,直接用强制转换是不行的,因为强制转换只能对标准数据类是不行的,因为强制转换只能对标准数据类型进行操作,对类类型的操作是没有定义的。型进行操作,对类类型的操作是没有定义的。转换运算符重载的缺点是无法定义其类对象转换运算符重载的缺点是无

35、法定义其类对象运算符操作的真正含义,因为只能进行相应运算符操作的真正含义,因为只能进行相应对象成员数据和一般数据变量的转换操作。对象成员数据和一般数据变量的转换操作。目录例例8.14运算符重载应用实例运算符重载应用实例 矩阵的基本运算矩阵的基本运算(加、减、乘法运算加、减、乘法运算)设计一个矩阵类:设计一个矩阵类:数据成员:数据成员:用一维数组模拟矩阵,存储矩阵中的数据:int*elems;用两个整型数据成员表示矩阵的行列数:short rows,cols;#include#include class matrixprivate:short rows,cols;int*elems;public

36、:matrix();matrix(short r,short c);matrix();int operator()(short row,short col);void disp();void setelem(short row,short col,int val);friend matrix operator+(matrix p,matrix q);friend matrix operator-(matrix p,matrix q);friend matrix operator*(matrix p,matrix q);matrix:matrix()elems=NULL;rows=cols=0;

37、matrix:matrix(short r,short c)rows=r;cols=c;elems=new int rows*cols;matrix:matrix()delete elems;void matrix:setelem(short row,short col,int val)if(row=1&row=1&col=cols)elems(row-1)*cols+(col-1)=val;void matrix:disp()for(int r=1;r=rows;+r)for(int c=1;c=cols;c+)cout setw(4)(*this)(r,c);cout=1&row=1&co

38、l=cols)return elems(row-1)*cols+(col-1);else return 0;matrix operator+(matrix p,matrix q)if(p.rows!=q.rows|p.cols!=q.cols)return matrix();matrix m(p.rows,p.cols);for(int r=1;r=m.rows;r+)for(int c=1;c=m.cols;+c)m.setelem(r,c,p(r,c)+q(r,c);return m;matrix operator-(matrix p,matrix q)if(p.rows!=q.rows|

39、p.cols!=q.cols)return matrix();matrix m(p.rows,p.cols);for(int r=1;r=m.rows;r+)for(int c=1;c=m.cols;c+)m.setelem(r,c,p(r,c)-q(r,c);return m;matrix operator*(matrix p,matrix q)if(p.cols!=q.rows)return matrix();matrix m(p.rows,q.cols);for(int r=1;r=m.rows;r+)for(int c=1;c=m.cols;c+)int s=0;for(int i=1

40、;i=p.cols;i+)s+=p(r,i)*q(i,c);m.setelem(r,c,s);return m;void main()matrix a(2,3),b(2,3),c(3,2),d(2,3),e(2,2);a.setelem(1,1,1);a.setelem(1,2,2);a.setelem(1,3,3);a.setelem(2,1,4);a.setelem(2,2,5);a.setelem(2,3,6);b.setelem(1,1,1);b.setelem(1,2,2);b.setelem(1,3,3);b.setelem(2,1,4);b.setelem(2,2,5);b.se

41、telem(2,3,6);c.setelem(1,1,1);c.setelem(1,2,4);c.setelem(2,1,2);c.setelem(2,2,5);c.setelem(3,1,3);c.setelem(3,2,6);cout A矩阵矩阵:endl;a.disp();cout B矩阵矩阵:endl;b.disp();cout C矩阵矩阵:endl;c.disp();d=a+b;cout A+B矩阵矩阵:endl;d.disp();d=a-b;cout A-B矩阵矩阵:endl;d.disp();e=a*c;cout A*C矩阵矩阵:endl;e.disp();A矩阵:矩阵:1 2 34 5 6B矩阵:矩阵:1 2 34 5 6C矩阵:矩阵:1 42 53 6A+B矩阵:矩阵:2 4 68 10 12A-B矩阵:矩阵:0 0 00 0 0A*C矩阵:矩阵:14 3232 77目录

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 生活常识

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁