第四章运算符重载C++面向对象程序设计C++语言程序设计2本章主要内容4.1什么是运算符重载4.2运算符重载的方法4.3重载运算符的规则4.4运算符重载函数作为类成员函数和友元函数4.5重载双目运算符4.6重载单目运算符4.7重载流插入运算符和流提取运算符4.8不同类型数据间的转换C++语言程序设计3【目的要求】1、掌握运算符重载的基础知识。2、掌握运算符重载函数为类成员函数及友元函数的方法。3、熟悉不同类型数据间的转换。【重点】运算符重载的方法;运算符重载函数作为类成员函数;运算符重载函数作为友元函数;单目运算符重载;不同类型数据之间的转换。【难点】单目运算符重载函数;不同类型数据间的转换。C++语言程序设计44.1什么是运算符重载函数的重载所谓函数的重载是指完成不同功能的函数可以具有相同的函数名。C++的编译器是根据函数的实参来确定应该调用哪一个函数的。运算符重载就是赋予已有的运算符多重含义。C++通过重新定义运算符,使它能够用于特定类的对象执行特定的功能C++语言程序设计5例如:“”是C++的位运算符中的左移运算符,但在输出操作中又是与流对象cout配合使用的流插入运算符。“”是右移运算符,但在输入操作中又是与流对象cin配合使用的流提取运算符。因此,如果程序中用“”和“”作流插入运算符和流提取运算符,必须在本文件模块中包含头文件iostream。例4.1没有用运算符重载,通过函数来实现两个复数相加。C++语言程序设计6#includeiostreamusingnamespacestd;classComplex{public:Complex(){real=0;imag=0;}//定义构造函数Complex(doubler,doublei){real=r;imag=i;}Complexcomplex_add(Complex&c2);voiddisplay();//声明输出函数private:doublereal;//实部doubleimag;//虚部};C++语言程序设计7ComplexComplex::complex_add(Complex&c2){Complexc;c.real=real+c2.real;//两个复数实部相加c.imag=imag+c2.imag;//两个复数虚部相加returnc;}voidComplex::display()//定义输出函数{cout(real,imagi)endl;}C++语言程序设计8intmain(){Complexc1(3,4),c2(5,-10),c3;c3=c1.complex_add(c2);//调用复数相加函数coutc1=;c1.display();coutc2=;c2.display();coutc1+c2=;c3.display();return0;}C++语言程序设计9运算结果是正确的。但能否进行:c3=c1+c2;的运算呢?4.2运算符重载的方法运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数。即:运算符重载实质上是函数的重载。重载运算符的一般格式为:函数类型operator运算符名称(形参表列){对运算符的重载处理}C++语言程序设计10例如:想将“+”用于Complex类(复数)的加法运算,函数的原型可以是:Complexoperator+(Complex&c1,Complex&c2);其中:operator是关键字,是专门用于定义重载运算符的函数的;运算符名称就是C++提供给用户的预下定义运算符。注意:函数名是由operator和运算符组成,即上面的operator+就是函数名,意思是:对运算符+重载。C++语言程序设计11定义了重载运算符的函数后,可出说:函数operator+重载了运算符+。如执行到复数相加:c3=c2+c1;时,系统就会调用operator+函数,把c1和c2作为实参。怎样理解运算符重载函数?对于普通函数,参数出现在圆括号内,而对于运算符重载函数,参数出现在其左、左两侧。例4.2重载运算符“+”,使之能用于两个复数对象的相加。C++语言程序设计12#includeiostreamusingnamespacestd;classComplex{public:Complex(){real=0;imag=0;}//默认构造函数(没有参数)Complex(doubler,doublei){real=r;imag=i;}//构造函数重载(有两个参数)Complexoperator+(Complex&c2);//声明重载运算符+的函数voiddisplay();private:doublereal;doubleimag;};C++语言程序设计13ComplexComplex::operator+(Complex&c2)//定义重载运算符+的函数{Complexc;c.real=real+c2.real;c.imag=imag+c2.imag;returnc;}voidComplex::display(){cout(real,imagi)endl;}C++语言程序设计14intmain(){Complexc1(3,4),c2(5,-10),c3;c3=c1+c2;//运算符+用于复数运算coutc1=;c1.display();coutc2=;c2.display();coutc1+c2=;c3.display();return0;}请比较例4.1与例4.2的不同。C++语言程序设计15说明:C++编译系统将程序中的表达式c1+c2解释为:c1.operator+(c2)//c1和c2是Complex类的对象即:以c2为实参调用c1的运算符重载函数operator+(Complex&c2),进行求值,得到两个复数之和。operator+是一个函数名,它是类Complex的成员函数(关于运算符重载函数用作类的成员函数,4.4节将继续介绍)。对于上面例子中的运算符重载函数operator+还可以写成:C++语言程序设计16ComplexComplex::operator+(Complex&c2)//定义重载运算符+的函数,函数体更简练{returnComplex(real+c2.real,imag+c2.imag);}参见:C4-2-2.CPPreturn语句是建立一个临时对象,它没有名字,是一个无名对象。在建立临时对象过程中调用构造函数。return语句将此临时对象作为函数返回值C++语言程序设计174.3重载运算符的规则1、C++不允许用户自己定义新的运算符,即只能对已有的C++运算符进行重载。2、C++允许重载的运算符见P125表4.1不能重载的运算符只有5个:.成员访问运算符.*成员指针访问运算符::域运算符sizeof长度运算符?:条件运算符C++语言程序设计183、重载运算符不能改变运算对象(即操作数)的个数。4、重载不能改变运算符的优先级别。5、重载不能改变运算符的结合性。6、重载运算符的函数不能有默认的参数。7、重载的运算符必须和用户定义的自定义的类型的对象一起使用,其参数至少应用一个是类对象(或类对象的引用)。8、运算符“=”和“&”用于类对象时,不需要重载。因为系统已经进行了重载。C++语言程序设计199、重载运算符的功能应类似于该运算符作用于标准类型数据时所实现的功能。10、运算符重载函数可能是类的成员函数(例4.2),也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数。(此种方式一般根本不会采用)4.4运算符重载函数作为类成员函数和友元函数例4.2程序中对运算符“+”进行了重载,并且重载函数operator+是作为Complex类中的成员函数的。由于重载函数是Complex类中的成员C++语言程序设计20函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员。如:real+c2.real就是This-real+c2.real将运算符重载为成员函数后,如出现含该运算符的表达式,如:c1+c2,编译系统把它解释为:c1.oporator+(c2)即通过对象c1调用运算符重载函数,并以表达式中第二个参数(c2)作为函数实参。c1.realC++语言程序设计21例4.3将运算符“+”重载为Complex类的友元函数。#includeiostream.hclassComplex{public:Complex(){real=0;imag=0;}Complex(doubler,doublei){real=r;imag=i;}friendComplexoperator+(Complex&c1,Complex&c2);//重载函数作为友元函数voiddisplay();private:doublereal;doubleimag;};C++语言程序设计22Complexoperator+(Complex&c1,Complex&c2)//定义作为友元函数的重载函数{returnComplex(c1.real+c2.real,c1.imag+c2.imag);}voidComplex::display(){cout(real,“imagi)endl;}C++语言程序设计23intmain(){Complexc1(3,4),c2(5,-10),c3;c3=c1+c2;coutc1=;c1.display();coutc2=;c2.display();coutc1+c2=;c3.display();return0;}此例与上例比较后区别如下:(1)运算符重载函数是作为Complex的友元函数C++语言程序设计24(2)运算符重载函数有两个参数。即c1+c2解释为:operator+(c1,c2)C++规定,有的运算符,如:赋值运算符、下标运算符、函数调用运算符必须定义为类的成员函数;有的运算符只能定义为友元函数,如:流插入()和流提取()运算符、类型转换运算符。一般:将单目运算符重载为成员函数,将双目运算符重载为友元函数。说明:VC6.0它提供的不带后缀.h的头文件不支持把成员函数重载为友元函数。故头文件采用#includeiostream.hC++语言程序设计254.5重载双目运算符双目运算符又称二元运算符,是C++中最常用的运算符。双目运算符有两个操作数,通常在运算符的左右两侧,如3+5,ab等。重载双目运算符,不言而喻在函数中应该有两个参数。例:4.4定义一个字符串类String,用来存放不定长的字符串,重载运算符“==”、“”和“”,用于两个字符串的等于、小于和大于的比较运算。C++语言程序设计26(1)先建立一个String类:见C4-4-1(VC++).CPP#includeiostreamusingnamespacestd;ClassString//String是用户自己指定的类名{public:String(){p=NULL;}//默认构造函数String(char*str);//构造函数voiddisplay();private:char*p;//字符型指针,用于指向字符串};C++语言程序设计27String::String(char*str)//定义构造函数{p=str;}//使p指向实参字符串voidString::display(){coutp;}//输出p所指向的字符串intmain(){Stringstring1(Hello),string2(Book);string1.display();coutendl;//换行string2.display();coutendl;return0;}C++语言程序设计28(2)增加“”运算符重载部分。C4-4-2(VC).CPP#includeiostream.h#includestring.hclassSt