《第8章 运算符的重载.ppt》由会员分享,可在线阅读,更多相关《第8章 运算符的重载.ppt(20页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第8章章 运算符的重载运算符的重载 本章要点:掌握运算符重载的目的和特点 掌握运算符重载的两种定义形式 掌握几种常用的运算符重载方法 掌握自定义类型的转换8.1 循序渐进学理论循序渐进学理论 8.1.1 运算符的重载运算符的重载 C+语言引入了运算符重载机制,程序员可以按照需要重新定义大部分的运算符,如“+”、“-”、“*”、“=”、“!”等,替换类中的成员函数,完成特定的功能。例如,针对复数类complex,重载加、减、乘、除运算符,分别代替加法成员函数Add(),减法成员函数Sub()、乘法成员函数Mul()和除法成员函数Div()。运算符重载只能适用于类类型和枚举类型,而不能重载基于内
2、嵌类型的运算符,更不能定义一种不存在的运算符。运算符重载也不能改变现有运算符的优先级、结合性、语法结构和操作数的个数。运算符重载从本质上说,也是一种函数的重载。8.1.2 运算符重载的定义运算符重载的定义1.成员函数形式 运算符重载的声明形式有两种:一是成员函数形式,二是友元函数形式。在成员函数形式中,运算符重载函数等同于一个类成员函数,在类体中被声明,格式如下:operator ()其中,operator是关键字,表明该成员函数是一个运算符重载函数。引用该运算符重载函数的类对象为第一操作数,参数表中的参数是第二操作数,因此对于单目运算符来说,参数表应该为空;对于双目运算符来说,参数表中只有一
3、个参数第二操作数。例如,在类String的定义中,有下列运算符重载函数:class String public:String&operator+(const String&);/重载加法运算符 bool operator=(const String&)const;/重载等于运算符 bool operator=(const char*)const;char&operator (int)const;/重载下标运算符 /;上述代码定义了三个运算符重载函数集。其中,等于运算符“=”不仅支持两个String类对象的比较,还支持String类对象和字符数组形式的字符串相比较。2.友元函数形式 定义一个友元
4、函数形式的运算符重载函数,必须完成两个动作:一是在全局域中定义一个运算符重载函数,格式如下:operator ()二是必须在类体中为它加上友元声明,格式如下:friend operator ();在友元函数形式的参数表中,第一个参数是第一操作数,第二个参数是第二操作数。因此,如果是单目运算符,则参数表中只有一个参数。例如,将上述类String中的等于运算符重载函数改写为友元函数形式:bool operator=(const String&,const String&);class String friend bool operator=(const String&,const String&)
5、;/3.如何选择运算符重载的形式 以上两种形式的运算符重载函数都是等效的,一般来说,当单目运算,或者双目运算中的第一个操作数是类对象时,选择成员函数形式;如果双目运算中的第一个操作数可能是其他类型时,选择友元函数形式。需要注意的是,赋值运算符“=”、下标运算符“”、调用运算符“()”和类成员箭头访问运算符“-”的重载,必须采用成员函数形式。8.1.3 赋值运算符的重载赋值运算符的重载 一般来说,应用在类对象上的运算符都必须经过重载,但是赋值运算符例外,系统会为类对象提供一个默认的赋值操作,完成类对象间的按成员赋值。如果默认的赋值操作不能满足要求,也可以重载赋值运算符,赋予它额外的功能。下面给出
6、【例8-1】的部分代码,示例如何定义定义了一个赋值运算符的重载函数。class Student public:Student(string i,int j):name(i),age(j)void Print()cout name ,age endl;Student&operator=(const Student&);/赋值运算符重载函数 private:int age;string name;Student&Student:operator=(const Student&a)if(this!=&a)/防止一个类对象向自己赋值 name=a.name;age=a.age;else cout 抱歉
7、,不允许自身复制!length-1|n0)cout报歉,数组下标越界!;return ch;else return strn;/返回下标指定的字符void disp()coutstrendl;8.1.5 算术运算符的重载算术运算符的重载 算术运算符是双目运算符。通常,双目运算符的重载都会采用友元函数形式,通过两个参数引入第一和第二操作数。如果第一操作数必须是该类的类对象时,也可以采用成员函数形式,这时候的第一操作数由this指针给出。下面给出【例8-3】的部分代码,示例如何重载算术运算符。class Student public:Student(string i,int j):name(i),
8、age(j)/友元函数 friend int operator-(const Student&,const Student&);string getName()return name;int getAge()return age;private:int age;string name;/减法运算符重载int operator-(const Student&a,const Student&b)return(a.age-b.age);8.1.6 递增递减运算符的重载递增递减运算符的重载 递增(+)和递减(-)运算符的重载相对来说会复杂一些,它们有前缀和后缀两种情况,所以在被重载的时候,会有两种声明
9、方式,格式如下:operator+();/前缀运算 operator+(int);/后缀运算 递增(+)和递减(-)运算符也可以声明为友元函数形式,它们在类体中的友元声明格式如下:friend operator+();/前缀运算 friend operator+(,int);/后缀运算 下面给出【例8-4】的部分代码,示例如何重载递增递减运算符。class A public:A()number=0;A(int i)number=i;int operator+()/递增运算符的前缀重载 return+number;/内嵌的递增运算符int operator+(int)/递增运算符的后缀重载 re
10、turn number+;/内嵌的递增运算符void Print()cout number=number endl;private:int number;1.为什么要提供自定义的类型转换?C+语言也支持用户自定义的类型转换,使得类对象的使用方式更加接近于内嵌类型,并且使程序看上去更加简单。例如,有一个类A,它重载了加法运算符,能够在类A的对象与对象之间,类A的对象与int型整数之间完成加法运算。例如:A a,b;/定义两个类A的对象a和b a+b;/两个操作数均为类对象 a+238;/类对象为第一操作数,int型整数为第二操作数 238+a;/int型整数为第一操作数,类对象为第二操作数,首先
11、,定义一个转换函数,将类A对象转换为int型,这样只需要为每一种运算符提供int型的重载函数就可以了,而不必考虑类A对象和int型变量在各种运算符中的排列组合情况。8.1.7 自定义类型转换自定义类型转换2.类型转换函数的定义 转换函数必须是成员函数,并且不能指定返回类型和参数表,它能够将类类型转换成某种指定的数据类型,其定义格式如下:operator()其中,数据类型可以是内嵌类型、类类型或者是typedef名,但不允许是数组或函数。例如,将类类型转换成整型的转换函数的声明如下:type char CHAR;operator int();/正确!operator CHAR();/正确!3.单
12、参数的构造函数作为转换函数 只有一个参数的构造函数也是一种隐式的类型转换函数,例如有下列代码:class A public:A(int i)/只有一个参数的构造函数 /;void fun(A x)/函数形参的类型为类A /int i;/定义一个int型变量 fun(i);/函数fun()中参数的类型应该是类A,语句中的实参却是int型变量i,它会导致编译错误吗?幸运的是,语句为类A定义了一个只有一个参数的构造函数,于是系统会自动调用该构造函数将变量i转换为类A的类对象。8.2 典型实例练能力典型实例练能力 8.2.1 典型实例一:典型实例一:自定自定义义矩矩阵阵的运算的运算 【实例题目】编写一个程序,实现矩阵的加法、减法和乘法运算。8.3 上机练习重应用上机练习重应用 8.3.1 上机练习一:复数的运算(二)上机练习一:复数的运算(二)【练习题目】改写6.3.1节的上机练习一,通过运算符的重载,实现复数的加法、减法、乘法,以及复数特定格式的输出。