第10章运算符重载
数据结构-运算符重载

Complex operator+(Complex &c1,Complex &c2) { Complex c; c.real=c1.real+c2.real; c.imag=c1.imag+c2.imag; return c; } void Complex::display( ) { cout<<"("<<real<<","<<imag<<"i)"<<endl; }
#include <iostream> using namespace std; class Complex { double real; double imag; public: Complex( ) { real=0; imag=0; } Complex(double r,double i):real(r),imag(i) {} friend Complex operator+(Complex &c1,Complex &c2); void display( ); };
10.1 什么是运算符重载
C++中预定义的运算符的操作对象只能是基 本数据类型。但实际上,对于许多用户自定 义的类型,也需要类似的运算。这时就必须 重新定义这些运算符,赋于已有运算符新的 功能,使之能够用于特定类型执行特定操作。
实际上,很多C++操作符已经被重载。例如, 将*操作符用于地址,将得到在这个地址中的 值;但将它用于两个数字时,得到的将是它 们的乘积。 C++根据操作数的数目和类型来决定采用哪 种操作。
C--程序设计--第10章-多态性及虚函数

使用重载函数注意:
不要使用重载函数描述不相干的函数 在类中,构造函数和普通成员函数均可以
重载 避免与函数的默认参数产生二义性
二、运算符重载
运算符重载(operate overloading)就是 赋予已有的运算符多重含义。
运算符重载实质是函数重载,运算符重载 的选择与函数重载类似,会根据运算符的 操作数的类型、个数和顺序来进行运算符 函数的选择。
#include<iostream.h> str#iinngc:l:usdter<isntgr(icnhga.rh>*s) v{}ossccsssc{s{{ittohtttolsstlsssls*drruarrrueptrepttepsi1trii3tc{pn=rin=rrn=pmn.<nn.<lprgncngncign=agp<*ggp<auitepgtepnte'irssrssbv\hwy:hwyghwnsit1ssitsla0=(:=(:=(tnr=ttnrit'scssscs:sc)rt1"rrt3scesss~ivci;thpt1hpsih1(.T23(.t::tttsnohn}ra,r.a,tza()gh(()grrrrttiatlrsilrsrer";eass;eiiiirdre[)ne[1i;[Ttt1ttnnnniglnl;gnl.nlhl)rlggggnep*e(e}(gesgeiei;2e(((gtrsnsnstnp(nsns)ncsi(lipg)gthg)ig(;(htn)en;t;tr;t;nti)a)artnthhih}ths<<ri{((;+n++<p<snd))}1g1s1aere*ige;]]i]nonszl{{;&;z;ddgd)&eercseelrl;s=teo1)m;a;/18etu)om/)0ut..;)构sr<""/;pn<造);//;s;/复}lp函构e<制n<数造ge构tn函hd造;l数};重} 载
运算符重载

说明:
Complex Complex::operator+(Complex c){ Complex Temp(Real+c.Real , Image+c.Image) ; return Temp ; }
当成员函数的参数为同一类(class)的对象或它的引 用,在函数体内使用参数对象的私有数据成员时,可 用对象名加成员访问操作符点号进行。 从逻辑上讲,每个对象有自己的成员函数,访问同类其 他对象的私有数据成员应通过该对象的公有函数,不 能直接访问。但在物理上只有一个成员函数代码,所 以直接访问是合理的。仅在成员函数中可以这样做。
int main(void){ Complex c1(1.0,1.0) , c2(2.0,2.0) , c3(4.0,4.0) , c; double d=0.5 ; c1.Print(); c=c2+c3; c.Print(); //两复数相加 c+=c2+=c1; c.Print(); //连续加赋值 c=c+d; c.Print(); //复数加实数 c=d+c; c.Print(); //实数加复数 c=c3*c2; c.Print(); c=c3/c1; c.Print(); c=c3*d; c.Print(); //复数乘以实数 c=c3/d; c.Print() ; //复数除以实数 cout<<"c3的模为:"<<abs(c3)<<endl ; return 0;}
4. C++中只有极少数的运算符不允许重载。
运算符
运算符名称
三目条件运算 符 成员与成员指 针操作符 作用域操作符 类型字长操作 符
禁止重载的理由
运算符重载

1、多态性的基本概念2、派生类对象替换基类对象3、虚函数的定义4、抽象类的定义5、宠物类的设计6、运算符重载7、日期类对象判断大小8、分数类对象运算符重载☐运算符重载指赋予运算符新的操作功能,主要用于对类的对象的操作☐运算符+意味着多少对象类型的加法呢?☐还可以定义新的对象类型加法☐运算符重载定义形式:<类型><类名>::operator<操作符>(<参数表>){函数体}☐首先定义虚数类☐虚数可以描述为:a+bi☐a与b看成实数,定义成double类型☐成员函数除了构造与析构外,还有:☐输出虚数、修改虚数、得到实部a、得到虚部b ☐相加+、判相等==#include <iostream>using namespace std;class Complex{private:double real, imag;public:Complex(double r = 0, double i = 0): real(r), imag(i){ }double Real(){return real;}double Imag(){return imag;}Complex operator +(Complex&);Complex operator +(double);bool operator ==(Complex);~Complex(){ };Complex Complex::operator +(Complex &c)// 重载运算符+,两边是虚数对象{Complex temp;temp.real = real+c.real;temp.imag = imag+c.imag;return temp;}Complex Complex::operator +(double d)// 重载运算符+,左边是虚数对象,右边是双精度数{Complex temp;temp.real = real+d;temp.imag=imag;return temp;}bool Complex::operator ==(Complex c)// 重载运算符=={if (real == c.real && imag == c.imag)return true;elseint main(){Complex c1(3,4),c2(5,6),c3;cout << "C1 = " << c1.Real() << "+j" << c1.Imag() << endl;cout << "C2 = " << c2.Real() << "+j" << c2.Imag() << endl;c3 = c1+c2;cout << "C3 = " << c3.Real() << "+j" << c3.Imag() << endl;c3 = c3+6.5;cout << "C3 + 6.5 = " << c3.Real() << "+j" << c3.Imag() << endl;if ( c1==c2 )cout<<“两个复数相等”;elsecout<<“两个复数不相等”;return 0;☐运算符++分前置运算符和后置运算符☐例如: ++Y与Y++☐前置运算符定义Complex Complex::operator ++ () {real+=1;return *this;}☐后置运算符定义Complex Complex::operator ++ (int) {real+=1;return *this;}。
运算符重载

例4.1 通过函数来实现复数相加 #include <iostream> using namespace std; class Complex { private: double real,image; public: Complex() { real=0; image=0; } Complex(double r,double i):real(r),image(i){} Complex complex_add(Complex &c2); void display(); };
4.4 重载运算符函数的设计
• 1. 重载运算符的返回值
–运算符函数的返回值类型一般都与当前类 的类型有关。 –运算符函数返回对象的值还是对象引用
• 原则:如果运算符形成的表达式(函数调用表达 式)需要作为左值则返回引用,否则返回值。
• ⑴+、-、*、/、%、后置的++和-– 因为加法、减法、乘法、除法和后置的加1和减1表达 式不能做左值,重载时应返回对象的值,故应采用类 似如下的函数原型: – Complex operator+(...); – Complex operator++(...);
+ ^ =
& <
* | >
/ ~ +=
% ! -=
*= |= == || ->
/= << != ++ []
%= >> <= -()
^= >>= >= >* New
&= <<= && , delete
.
.*
::
运算符重载

{
rpart=rp;
ipart=ip;
}
Complex add( const Complex & com )
{
Complex temp ;
temp .rpart= com .rpart+rpart;
temp .ipart= com .ip+ipart;
return temp ;
}
2020/7/2
பைடு நூலகம்};
★单目运算符重载 :
Complex Complex:: operator {
Complex temp;
( 单) 目无参数 双目一个参数
temp.rpart=-rpart;
temp.ipart)=-ipart;
return temp;
}
Complex c=-a+b;
(a.operator-( )).operator+(b)
};
point point::operator+ (point p1)
{ point p; p.x=x+p1.x; p.y=y+p1.y; return p; }
void main()
{ point p1(10,10),p2(20,20); p1=p1+p2 ;
p1.print(); ++p1; p1.print();
}
//(╳)
运算符成员函数——调用成员函数的对象隐式成为表达式的第一个运算数 外部运算符函数——其第一个参数直接对应表达式的第一个运算数;
x1=x2+x3;
operator+(x2, x3);
2020/7/2
6 6
运算符重载

24
运算符重载
思考:如果希望表达式i+c1有意义, 思考:如果希望表达式i+c1有意义,应该 i+c1有意义 如何定义重载运算符函数? 如何定义重载运算符函数?
friend Complex operator+(int &i,Complex &c); Complex operator+(int &i, Complex &c) {return Complex(i+c.real,c.imag);}
2
什么是运算符重载
代码分析: 代码分析: 例10.1 通过函数来实现复数 相加。 相加。
CCS E
3
运算符重载的方法
运算符重载的方法是定义一个重载运 算符的函数, 算符的函数,在需要执行被重载的运 算符时,系统就自动调用该函数, 算符时,系统就自动调用该函数,以 实现相应的运算。也就是说, 实现相应的运算。也就是说,运算符 重载是通过定义函数实现的。 重载是通过定义函数实现的。运算符 重载实质上是函数的重载。 重载实质上是函数的重载。
CCS E
21
运算符重载
如果将运算符重载函数作为成员函数, 如果将运算符重载函数作为成员函数, 它可以通过this this指针自由地访问本类 它可以通过this指针自由地访问本类 的数据成员, 的数据成员,因此可以少写一个函数 的参数。 的参数。但必须要求运算表达式第一 个参数(即运算符左侧的操作数) 个参数(即运算符左侧的操作数)是一 个类对象, 个类对象,而且与运算符函数的类型 相同。 相同。因为必须通过类的对象去调用 该类的成员函数,而且只有运算符重 该类的成员函数, 载函数返回值与该对象同类型, 载函数返回值与该对象同类型,运算 结果才有意义。 结果才有意义。
运算符重载

运算符重载为类的友元函数
类中的声明: 类中的声明: friend 函数类型 operator 运算符(参数表); 运算符(参数表); 运算符重载函数的定义形式: 运算符重载函数的定义形式: 运算符(参数表) 函数类型 operator 运算符(参数表) { 函数体; 函数体; } 附加例) (附加例)用友元函数实现复数的加法运算符的重 载。
数据类型转换 标准数据类型转换
隐式转换: 自动转成double型) 隐式转换:7.5+2 (将2自动转成 将 自动转成 型 显式转换: 转成整型) 显式转换:int(89.5) (将89.5转成整型 将 转成型
涉及到类类型的转换
对于用户自己声明的类型, 对于用户自己声明的类型,编译系统并不知道怎样进行转 换。解决这个问题的关键是让编译系统知道怎样去进行转 换,需要定义专门的处理函数。 需要定义专门的处理函数。 将一个其他类型的数据转换成一个类类型: 将一个其他类型的数据转换成一个类类型:转换构造函数 将一个类的对象转换成另一类型的数据: 将一个类的对象转换成另一类型的数据:类型转换函数
运算符重载的格式
运算符重载为类的成员函数 运算符重载为类的友元函数
运算符重载的规则
①
② ③ ④ ⑤
.”、 *” ::”、 ?:”和 sizeof”等几个运 除“. 、“*”、“:: 、“?: 和“sizeof 等几个运 算符不能重载外, 算符不能重载外,C++中几乎所有的运算符都可以 中几乎所有的运算符都可以 重载。 重载。 运算符被重载后,其优先级和结合性不会改变。 运算符被重载后,其优先级和结合性不会改变。 不能改变运算符操作对象的个数。 不能改变运算符操作对象的个数。 运算符的意义应不变。 运算符的意义应不变。 用于类对象的运算符一般必须重载,但有两个例外, 用于类对象的运算符一般必须重载,但有两个例外, 运算符“ 和 不必用户重载。 运算符“=”和“&”不必用户重载。 不必用户重载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c.imag=imag+c2.imag;
return c;}
void Complex∷display( )
//定义输出函数
{cout<<″(″<<real<<″,″<<imag<<″i)″<<endl;}
int main( )
{Complex c1(3,4),c2(5,-10),c3;
//定义3个复数对象
void display43;取代了 complex_add
double real;double imag;
}; Complex Complex∷operator+(Complex &c2) //定义重载运算
符的函数 { Complex c;
隐含this指针
c.real=real+c2.real;
《C++程序设计 》网 络 教 学
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
10.1 什么是运算符重载
函数重载就是对一个已有的函数赋予新的含义, 使之实现新功能。
用户能根据自己的需要对C++已提供的运算符进 行重载,赋予它们新的含义,使之一名多用。 例如10.1 :用“+”号进行两个复数的相加。在 C++中不能在程序中直接用运算符“+”对复数进 行相加运算。用户必须自己设法实现复数相加。
c3=plex_add(c2);
//调用复数相加函数
cout<<″c1=″; c1.display( );
//输出c1的值
cout<<″c2=″; c2.display( );
//输出c2的值
cout<<″c1+c2=″; c3.display( );
//输出c3的值
return 0;
} 运行结果如下: c1=(3,4i)
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
在定义了重载运算符的函数后,可以说:函数 operator+重载了运算符+。为了说明在运算符重载 后,执行表达式就是调用函数的过程,可以把两个 整数相加也想像为调用下面的函数:
int operator + (int a,int b) {return (a+b);}
private:
double real;
//实部
double imag;
//虚部
};
Complex Complex∷complex_add(Complex &c2)
{Complex c;
c.real=real+c2.real;
《C++程序设计 》网 络 教 学
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
相加。
#include <iostream>
using namespace std;
class Complex
{public:
Complex( ){real=0;imag=0;}
Complex(double r,double i){real=r;imag=i;}
Complex operator+(Complex &c2); //声明重载运算符的函数
函数类型 operator 运算符名称 (形参表列) { 对运算符的重载处理 } 例如,想将“+”用于Complex类(复数)的加法运算, 函数的原型可以是这样的:
Complex operator+ (Complex& c1,Complex& c2);
《C++程序设计 》网 络 教 学
电子与信息工程系
int main( )
c3=plex_add(c2);
{ Complex c1(3,4),c2(5,-10),c3; c1+c2
c3=c1+c2;
//运算解符释+为用: 于c1复.op数er运at算or+(c2)
《C++程序设计 》网 络 教 学
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
例10.1 通过函数来实现复数相加。
#include <iostream>
using namespace std;
class Complex
//定义Complex类
{public:
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
第10章 运算符重载
10.1 什么是运算符重载 10.2 运算符重载的方法 10.3 重载运算符的规则 10.4 运算符重载函数作为类成员函数和友元函数 10.5 重载双目运算符 10.6 重载单目运算符 10.7 重载流插入运算符和流提取运算符 10.8 不同类型数据间的转换
Complex( ){real=0;imag=0;}
//定义构造函数
Complex(double r,double i){real=r;imag=i;} //构造函数重载
Complex complex_add(Complex &c2); //声明复数相加函数
void display( );
//声明输出函数
如果有表达式5+8,就调用此函数,将5和8作为调 用函数时的实参,函数的返回值为13。这就是用函 数的方法理解运算符。
《C++程序设计 》网 络 教 学
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
例10.2 改写例10.1,重载运算符“+”,使之能用于两个复数
能否直接用加号“+”来实现 复数运算呢?如:c3=c1+c2;
c2=(5,-10i)
c1+c2=(8,-6i)
《C++程序设计 》网 络 教 学
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
10.2 运算符重载的方法
运算符重载的方法是定义一个重载运算符的函数, 在需要执行被重载的运算符时,系统就自动调用该 函数,以实现相应的运算。重载运算符的函数一般 格式如下:
c.imag=imag+c2.imag;
《C++程序设计 》网 络 教 学
电子与信息工程系
COMPUTER SCIENCE & TECHNOLOGY DEPARTMENT
return c;}
void Complex∷display( )
{ cout<<″(″<<real<<″,″<<imag<<″i)″<<endl;}