资源预览内容
第1页 / 共81页
第2页 / 共81页
第3页 / 共81页
第4页 / 共81页
第5页 / 共81页
第6页 / 共81页
第7页 / 共81页
第8页 / 共81页
第9页 / 共81页
第10页 / 共81页
亲,该文档总共81页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
第四章 运算符重载,4.1什么是运算符重载 4.2运算符重载的方法 4.3重载运算符的规则 4.4运算符重载函数作为类成员函数和友元函数 4.5重载双目运算符 4.6重载单目运算符 4.7重载流插入运算符和流提取运算符 4.8不同类型数据间的转换,4.1什么是运算符重载,C+ 为程序员提供了灵活的手段,让程序员自己定义类,自己设计相应的运算符(必须在已有的运算符基础上设计),使之应用于自己定义的类。与函数重载类似,对已有的运算符赋予新的含义,用一个运算符表示不同功能的运算,这就是运算符重载。 实际上,我们在此之前已经使用了运算符重载。如是C+的移位运算符,它又与流对象cout配合作为流插入运算符,这是C+对进行了重载处理。,运算符重载的实质,运算符重载是对已有的运算符赋予多重含义。 必要性 C+中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类) 实现机制 将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。 编译系统对重载运算符的选择,遵循函数重载的选择原则。,例4.1 通过成员函数实现复数的加法。 class Complex private: double real; double imag; public: Complex()real=0;imag=0; Complex(double r,double i)real=r;imag=i; Complex complex_add(Complex ,Complex Complex:complex_add(Complex ,在Complex类中定义了complex_add函数做加法,函数的参数是引用对象,作为一个加数。在函数里定义了临时对象c,两个赋值语句相当于: c.real = this-real +c2.real; c.imag = this-imag+c2.imag; 在main函数中通过对象c1调用加法函数,上面的语句相当于: c.real = c1.real +c2.real; c.imag = c1.imag+c2.imag; 能否用+运算符实现复数加法?,4.2运算符重载的方法,运算符重载的方法是定义一个重载运算符函数,在需要时系统自动调用该函数,完成相应的运算。运算符重载实质上是函数的重载。运算符重载函数的格式是: 数据类型 operator 运算符(形参表) 重载处理 数据类型:是重载函数值的数据类型。 operator 是保留字,规则和限制,C+中可以重载除下列运算符外的所有运算符: . .* : ?: sizeof() 只能重载C+语言中已有的运算符,不可臆造新的。 不改变原运算符的优先级和结合性。 不能改变操作数个数。 经重载的运算符,其操作数中至少应该有一个是自定义类型。,两种形式,重载为类成员函数。 重载为友元函数。,运算符函数,声明形式 函数类型 operator 运算符(形参) 重载为类成员函数时 参数个数=原操作数个数-1 (后置+、-除外) 重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。,不能重载的运算符只有5个: . 成员运算符 .* 成员指针运算符 : 域运算符 sizeof 长度运算符 ?: 条件运算符 重载函数名是由operator和运算符联合组成。 复数加法运算符重载函数原型可以是: Complex operator+ (Complex 例4.2 重载运算符+,用于两个复数相加。,分析:定义一个复数类,用成员函数实现加号的重载函数。两个复数相加结果仍是复数,所以函数的返回值的类型也是复数类。用成员函数实现运算符重载函数时,调用格式是“对象名.成员名”,此时对象就是一个参与运算的操作数,加法还需要另一个操作数,这个操作数用函数的参数传递,参数的类型就是复数类。而运算结果用函数值返回。,class Complex public: Complex()real=0;imag=0; Complex(double r,double i)real=r;imag=i; Complex operator + (Complex ,Complex Complex:operator + (Complex ,int main() Complex c1(3,4),c2(5,-10),c3; c3=c1+c2; cout“c1=“;c1.display(); cout“c2=“;c2.display(); cout“c1+c2=“;c3.display(); return 0; ,说明: (1)用运算符重载函数取代了例 4.1中的加法成员函数,从外观上看函数体和函数返回值都是相同的。 (2)在主函数中的表达式c3=c2+c1 取代了例4.1中的c3=c1.complex_add(c2) ,编译系统将表达式c3=c1+c2 解释为 c1.operator + ( c2 ) 对象c1调用的重载函数operator + ,以c2为实参计算两个复数之和。,请考虑在例4.2中能否用一个常量和一个复数相加?如 c3 = 3 + c2; / 错误 应该定义对象:Complex C1(3.0,0) : c3 = C1 + c2; 注意:运算符重载后,其原来的功能仍然保留,编译系统根据运算表达式的上下文决定是否调用运算符重载函数。 运算符重载和类结合起来,可以在C+ 中定义使用方便的新数据类型。,4.3重载运算符的规则,(1)C+只允许已有的部分运算符实施重载。 (2)不能重载的运算符有五个。 (3)重载不改变操作数的个数。 (4)重载不改变运算符的优先级。 (5)运算符重载函数不能带默认值参数。 (6)运算符重载函数必须与自定义类型的对象联合使用,其参数至少有一个类对象或类对象引用。 (7)C+默认提供 = 和 & 运算符重载。,(8)运算符重载函数可以是类成员函数也可以是类的友元函数,还可以是普通函数。 (9)C+规定赋值运算符、下标运算符、函数调用运算符必须定义为类的成员函数;而输出流插入、输入流提取、类型转换运算符不能定义为类的成员函数。,4.4运算符重载函数作为类成员函数和友元函数,在例4.2程序中对运算符+进行了重载,该例将运算符重载函数定义为复数类的成员函数。 从该程序中看到运算符重载为成员函数时,带一个类类型的形参,而另一个加数就是对象自己。 例4.3 将加法运算符重载为适用于复数加法,重载函数作为类的友元函数。,#include class Complex public: Complex () real=0;imag=0; Complex (double r) real=r;imag=0; Complex (double r,double i) real=r;imag=i; friend Complex operator+ (Complex ,Complex operator+ (Complex ,int main() Complex c1(3,4),c2(5,-10),c3; c3=c1+c2; cout“c1=“; c1.display(); cout“c2=“; c2.display(); cout“c1+c2=“; c3.display(); return 0; ,加法运算符重载为友元函数,C+ 在编译时将表达式c1+c2解释为 operator + ( c1, c2) 即相当于执行以下函数 Complex operator + ( Complex 因为普通函数是不能直接访问对象的私有成员,如果普通函数必须访问对象的私有成员,可调用类的公有成员函数访问对象的私有成员。这会降低效率。,书上的错误,如想将一个复数和一个整数相加,运算符重载函数作为成员函数定义如下: Complex Complex :operator + ( int 注意在运算符+的左侧必须是Complex类对象,程序中可以写成: c3 = c2 + n 不能写成: c3 = n + c2,书上的错误,如果要求在使用重载运算符时,运算符左侧操作数不是对象,就不能使用前面定义的运算符重载函数,可以将运算符重载函数定义为友元函数: friend Complex operator + ( int 友元函数不要求第一个参数必须是类类型,但是要求实参要与形参一一对应: c3 = n + c2 / 顺序正确 c3 = c2 +n / 顺序错误,为了实现加法的交换率,必须定义两个运算符重载函数,记住成员函数要求运算符左侧的操作数必须是自定义类型的对象,而友元函数没有这个限制,可以用下面两个组合中任意一个: (1)成员函数(左操作数是对象,右操作数是非对象)、友元函数(左操作数是非对象,右操作数是对象) (2)友元函数(左操作数是对象,右操作数是非对象)、友元函数(左操作数是非对象,右操作数是对象),由于使用友元会破坏类的封装,要尽量将运算符重载函数定义为成员函数。但考虑到各方面的因素,一般将单目运算符重载为成员函数,将双目运算符重载为友元函数。 VC+6.0的不带后缀h的头文件不支持把成员函数重载为友元函数。但VC+6.0带后缀h的头文件支持这项功能,所以要将程序中的语句: #include using namespace std; 改成: #include 即可正常运行。,4.5重载双目运算符,双目的意思是运算符左边和右边的操作数均参加运算。 如果要重载 B 为类成员函数,使之能够实现表达式 oprd1 B oprd2,其中 oprd1 为A 类对象,则 B 应被重载为 A 类的成员函数,形参类型应该是 oprd2 所属的类型。 经重载后,表达式 oprd1 B oprd2 相当于 oprd1.operator B(oprd2)。,例4.4 定义一个字符串类String,用来处理不定长的字符串,重载相等、大于、小于关系运算符,用于两个字符串的等于、大于、小于的比较运算。 操作数:两个操作数都是字符串类的对象。 规则:两个字符串进行比较。 将“”运算重载为字符串类的成员函数。,(1)先建立一个String类 #include #include class String / String 是用户自己指定的类名 public: String() p=NULL; String( char *str ) ; void display(); private: char *p; ;,String:String(char *str) p=str; void String:display() coutp; int main() String string1(“Hello“),string2(“Book“); string1.display(); coutendl; string2.display(); return 0; ,先编写出简单的程序框架,编写和调试都比较方便。构造函数是把定义对象时的实参的地址赋予数据成员p,p是指向实参的指针。程序实现了建立对象、输出字符串对象的功能。程序运行结果分别输出 Hello Book (2)有了这个基础后,再增加所需的其他内容,先重载大于运算符。程序如下:,/本程序适用于VC+ 6.0 #include #include class String public: String () p=NULL; String (char *str); void display(); friend bool operator(String ,void String:display() cout(String ,运算符重载函数定义为友元函数,函数值是布尔类型,在函数中调用了strcmp库函数,s
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号