资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第,9,章运算符重载,目 录,9,1,运算符重载概述,9,3,双目运算符重载,9,4,比较运算符重载,9,5,赋值运算符重载,问题引入:,#include,class Complex,public:,Complex(),real=0.0;,imag,=0.0;,Complex(double,r,double i),real=r;,imag,=i;,void display(),cout,real“+”image“i”,endl,;,private:,double real;,double,imag,;,Complex a(10,20),b(5,8),c;,c=,a+b,?,9,1,运算符重载概述,c+,中预定义的运算符的操作对象只能是,基本数据类型,很多用户自定义类型(比如类),也需要有类似的运算操作,这就提出了对运算符进行重新定义,赋予已有符号以新功能的要求。,运算符重载是对已有的运算符赋予多重含义,同一个运算符作用于不同类型的数据导致不同类型的行为。,返回目录,运算符重载的实质就是函数重载。,9,1,运算符重载概述,!,+,-,*,&,/,%,=,=,!=,|,&,+=,-=,*,=,/=,%=,&=,=,|=,=,-*,-,(),=,+,-,new,delete,表,9.1 C+,中可以重载的运算符,表,9,2 C+,中不能重载的运算符,.,.*,:,?:,返回目录,9,1,运算符重载概述,运算符重载的规则如下:,C+,中的运算符除了少数几个之外,全部可以重载,而且,只能重载已有的这些运算符,。,重载之后运算符的,优先级和结合性都不会改变,。,重载不能改变原运算符的,操作对象个数,,同时,至少要有一个操作对象是自定义类型,。,一般来讲,重载的,功能应当与原有功能相类似,。,返回目录,9,1,运算符重载概述,friend,函数类型,operator,运算符,(,形参表,),当重载为,类的友元函数,时,参数个数,与原运算数的个数相同。,函数类型,operator,运算符,(,形参表,),当运算符重载为,类的成员函数,时,函数的参数个数比原来的运算数个数要少一个,(,后缀,+,、,-,除外,),;,运算符的重载形式有两种:,重载为类的友元函数,重载为类的成员函数,返回目录,9,1,运算符重载概述,#include,class Complex,public:,Complex()real=0.0;,imag,=0.0;,Complex(double,r=0.0,double i=0.0)real=r;,imag,=i;,void display(),cout,real“+”image“i”,=,只能重载为,非成员函数,的情况,:,你自定义的类是第二个操作数,9,1,运算符重载概述(完),返回目录,最好这样做,9,3,双目运算符重载,双目运算符重载为类的成员函数,返回目录,oprd1 B oprd2,class Complex,public:,Complex()real=0.0;,imag,=0.0;,Complex(double,r,double i)real=r;,imag,=i;,void display(),cout,real+,imag,i,endl,;,Complex operator+(const Complex,Complex operator (const Complex,private:,double real;,double,imag,;,;,9,3,双目运算符重载,返回目录,Complex,Complex:operator,+(const Complex&s1),Complex s;,s.real,=real+s1.real;,s.imag,=imag+s1.imag;,return s;,Complex,Complex:operator,-(const Complex&s1),Complex s;,s.real,=real-s1.real;,s.imag,=,imag,-s1.imag;,return s;,对象本身是左操作数,右操作数为参数,9,3,双目运算符重载,void main(),Complex 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();,返回目录,v1=6,8i,v2=3,6i,v1+v2=9,14i,v1-v2=3,2i,9,3,双目运算符重载,双目运算符重载为类的友元函数,返回目录,class Complex,public:,Complex()real=0.0;,imag,=0.0;,Complex(double,r,double i)real=r;,imag,=i;,void display(),cout,real+,imag,i,endl,;,private:,double real;,double,imag,;,friend Complex,operator+(const,Complex,friend Complex operator-(const Complex,;,9,3,双目运算符重载,Complex operator+(const Complex&s1,const Complex&s2),Complex s;,s.real,=s1.real+s2.real;,s.imag,=s1.imag+s2.imag;,return s;,Complex operator-(const Complex&s1,const Complex&s2),Complex s;,s.real,=s1.real-s2.real;,s.imag,=s1.imag-s2.imag;,return s;,返回目录,第一个参数为左操作数,第二个参数为右操作数,9,3,双目运算符重载(完),void main(),Complex v1(6,8),v2(3,6),v3,v4;,cout,v1=;v1.display();,cout,v2=;v2.display();,v3=v1+v2;,/v3=operator+(v1,v2);,cout,v1+v2=;,v3.display();,v4=v1-v2;,/v4=operator+(v1,v2);,cout,、,或,=),的重载函数。,比较运算符重载函数必须返回真,(true/,非,0),或假,(false/0),。,返回目录,class Complex,public:,Complex()real=0.0;,imag,=0.0;,Complex(double,r,double i)real=r;,imag,=i;,void display(),cout,real+,imag,i,endl,;,Complex,operator+(const,Complex,Complex operator-(const Complex,bool,operator=(const Complex,bool,operator!=(const Complex,private:,double real;,double,imag,;,;,9,4,比较运算符重载,bool,Complex:operator=(const Complex&s1),if(real,=s1.real)&(imag=s1.imag),return true;,else,return false;,bool,Complex:operator!=(const Complex&s1),if(real,!=s1.real)|(imag!=s1.imag),return true;,else,reurn,false;,return !(*this=s1);,9,4,比较运算符重载,(,完,),void main(),Complex a(3,4),b(5,6),c(8,10);,if(,a+b,)=c),cout,“,相等,!”,endl,;,else,cout,“,不等,”,endl,;,(,a.operator+(b,).operator=(c),9,5,赋值运算符重载,在,C+,中有两种类型的赋值运算符:,、,.,适于实现为类的成员函数,返回目录,9,5,1,运算符“,=”,的重载,赋值运算符“,=”,的原有含义是将赋值号右边表达式的结果,拷贝,给赋值号左边的变量。,为了保证同类对象之间能够进行赋值操作,,每个类应定义赋值操作,(重载运算符)。,如果程序中没有定义赋值操作,则,c,编译器,自动生成,,实现将赋值号右边对象的数据成员依次拷贝到赋值号左边对象的数据成员中。,class Complex,public:,Complex()real=0.0;,imag,=0.0;,Complex(double,r,double i)real=r;,imag,=i;,Complex(const,Complex&s)real=,s.real,;,imag,=,s.imag,;,void display(),cout,real+,imag,i,endl,;,complex,operator+(const,complex,complex operator-(const complex,bool,operator=(const complex,bool,operator!=(const complex,Complex,&,operator=(const Complex,private:,double real;,double,imag,;,;,Complex,&,Complex:operator=(const Complex&s1),real=s1.real;,imag,=s1.imag;,return *this;,void main(),Complex a(2,3);,Complex b=a;,Complex,c,d,;,d=c=a;,9,5,2,运算符“,+=”,和“,-=”,的重载,对于标准数据类型,“,+=”,和“,-=”,的作用是将一个数据与另一个数据进行加法或减法运算后再将结果回送给赋值号左边的变量中。,a+=b,a=,a+b,class Complex,public:,Complex()real=0.0;,imag,=0.0;,Complex(double,r=0.0,double i=0.0)real=r;,imag,=i;,Complex(const,Complex&s)real=,s.real,;,imag,=,s.imag,;,void display(),cout,real+,imag,i,endl,;,Complex,operator+(const,Complex,Complex operator-(const Complex,bool,operator=(const Complex,bool,operator!=(const Complex,Complex,Complex,private:,double real;,double,imag,;,friend Complex&operator+=(Complex&s1,const Complex,;,Complex&,Complex:operator,-=(const Complex&s1),real-=s1.real;,imag,-=s1.imag;,return*this;,Complex&operator+=(,Complex&s1,const Complex&s2),s1.real+=s2.real;,s1.imag+=s2.imag;,return s1;,void main(),complex s1(3,4),s2(5,6),s3;,s3+=s1;,s3-=s1;,这两个成员函数必须有,若没有,系统自动为类创建,提供缺省实现。,什么时候不使用使用缺省实现?,不,需要,拷贝所有,的数据成员。,要,做其他的事情。,数据成员中,有指针类型时,(默认的实现的是浅拷贝,浅拷贝会带来安全上的隐患),探讨:,拷贝构造函数,和,=,运算符重载函数,浅拷贝带来的悬挂指针问题,class M,public:,M(int,i);,M();,void print();,private:,int,*p;,;,M:M(int,i),p=new,int(i,);,M:M(),delete p;,编译器自动生成:,M:M(const,M&,m):p(m.p,),M&,M:operator,=(const M&m),p=,m.p,;,return*this;,5,a,M a(5),b(a);,b,5,a,M a(5),b(7);,7,b,b=a,5,a,7,b,浅拷贝带来的悬挂指针问题,自己定义(深拷贝),M:M(const,M&m),p=new,int,;,*p=*(,m.p,);,M&,M:operator,=(const M&m),*p=*(,m.p,);,return*this;,5,a,M a(5),b(7);,7,b,a=b,7,a,7,b,5,a,M a(5),b(a);,b,5,编译器自动生成:,M:M(const,M&,m):p(m.p,),M&,M:operator,=(const M&m),p=,m.p,;,return*this;,例:用,char*,表示姓名,class Student,int,no;,int,grade;,char*name;,Student()name,=NULL;,Student(int,n,int,g,char,*,na,),no=n;,grade=g;,name=new charstrlen(na)+1;,strcpy(name,na,);,Student()delete,name;,必须自己写,拷贝构造函数,和,=,自动生成,Student(const,Student&s),no=,s.no,;,grade=,s.grade,;,name=,s.name,;,自定义,Student(const,Student&s),no=,s.no,;,grade=,s.grade,;,name=new charstrlen(s.name)+1;,strcpy(name,s.name,);,自动生成,Student&operator=(const Student&s),no=,s.no,;,grade=,s.grade,;,name=,s.name,;,return*this;,自定义,Student&operator=(const Student&s),no=,s.no,;,grade=,s.grade,;,if(this,!=&s),delete name;,name=new charstrlen(s.name)+1;,strcpy(name,s.name,);,return*this;,例:,定义一个整型数组类,class Array,private:,int,*,ptr,;,int,size;,public:,Array(int,arraySize,=10);,Array(int,int,);,Array(const,Array,Array,Array()delete ,ptr,;,int,getSize()const,return,size;,void set(int i,int g)ptri=g;,int get(int i)return ptri;,;,能创建特定大小的数组,能用一个系统数组初始化你的数组,能用同类型的其他数组初始化你的数组,两个数组可以互相赋值,Array:Array(int,arraySize,),size=,arraySize,;,ptr,=new,int,size;,for(int,i=0;i,size;i,+),ptri,=0;,Array:Array(int,a,int,s),size=s;,ptr,=new,intsize,;,for(int,i=0;i,size;i,+),ptri,=,ai,;,Array:Array(const,Array&init),size=,init.size,;,ptr,=new,intsize,;,for(int,i=0;i,size;i,+),ptri=init.ptri;,Array&,Array:operator,=(const Array&right),if(&right,!=this),delete,ptr,;,size=,right.size,;,ptr,=new,intsize,;,for(int,i=0;i,size;i,+),ptri,=,right.ptri,;,return*this;,9,2,单目运算符重载,“,+”,、“,-”,运算符有前缀和后缀两种使用形式,重载运算符也有前缀和后缀两种运算符重载形式,以“,+”,重载运算符为例,其语法格式如下:,返回目录,函数类型,operator+();/,前缀运算,函数类型,operator+(,int,);/,后缀运算,使用前缀运算符的语法格式如下:,+,对象,;,使用后缀运算符的语法格式如下:,对象,+;,例,9.1,,,9.2,#include,class Sample,public:,Sample(int,i):,n(i,),void operator+()n+=1;/,前缀运算符,void operator+(,int,)n+=2;/,后缀运算符,void display(),cout,n=n,endl,;,private:,int,n;,;,void main(),Sample a(5),b(5);,+b;,b.display,();/,调用前缀运算符重载,a+;,a.display,();/,调用后缀运算符重载,返回目录,n=7,n=6,缺陷:,Sample a,b(5);,a=+b;/,错误,#include,class Count,public:,Count(int,i=0):,n(i,),Count&operator+(),+n;,return*this;,Count,operator+(int,),Sample temp=*this;,+n;,return temp;,private:,int,n;,;,return,Count(n,+);,Sample a(4),b(0);,b=a+;/,b.n,为,4,b=+a;/,b.n,为,6,
展开阅读全文