运算符重载
2016-07-18 18:04
106 查看
一、什么是运算符重载
我们知道函数重载就是对已有的函数赋予新的含义,使之实现新的功能。因此,同一个函数可以实现不同的功能,也就是一名多用。
运算符也可以重载,像我们平时使用的+运算符,对整形,单精度浮点型,双精度浮点型都能实现加法运算。又如,<<(左移),在输出操作中与流对象cout配合使用实现输出操作。>>(右移),在输入操作中与流对象cin配合使用实现输入操作。
在C++程序中,用户不能直接用C++提供的运算符来实现用户自定义类的运算,所以用户必须根据自己的需要对C++提供的运算符进行重载,赋予他们新的含义。
二、运算符重载的方法
运算符重载的方法是定义一个重载运算符函数,在需要执行被重载的运算符时,系统自动调用该函数。所以运算符重载实际上是函数的重载。
重载运算符的函数格式如下:
函数类型 operator 运算符名称(形参列表)
{对运算符的重载处理}
例:实现一个复数类,并重载+运算符
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
Complex(
double
real =0,
double imag=0) :_real(real
)
//构造函数
, _imag(
imag)
[align=left] {[/align]
[align=left] }[/align]
Complex
operator+(Complex
c2)
//对+运算符重载,使之能进行复数相加
[align=left] {[/align]
return
Complex (_real+c2._real,_imag+
c2._imag);
[align=left] }[/align]
void
display()
//打印函数
[align=left] {[/align]
cout <<
"("
<< _real << ","
<< _imag <<
"i" <<
")" << endl;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1(2.3,4.1);
Complex
c2(1.4, 2.8);
Complex
c3;
system(
"pause");
return
0;
[align=left]}[/align]
在上面的函数中,实现了+运算符重载,使+能够进行复数对象之间的运算。值得注意的是,运算符在被重载后,其原有的功能仍然保留。
三、运算符重载的规则
1、C++不允许用户自己定义新的运算符,只能对已有的运算符进行重载。
2、C++中不能重载的运算符只有五个,剩下的都可以重载
.(成员访问运算符)
.*(成员指针访问运算符)
::(作用域解析符)
sizeof(长度运算符)
?:(条件运算符)
3、重载不能改变运算符运算对象的个数(即操作数的个数)
4、重载不改变运算符的优先级别
5、重载不改变运算符的结合性
6、重载的运算符必须和用户自定义的自定义类型的对象一起使用,其参数至少应该有一个是类对象(或类的引用),防止用户修改用于标准类型数据的运算符的性质,比如下面这样
int operator+(int a,int b)
{ return a-b;}
会产生二义性。
7、用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载,类默认生成的。
8、一般将单目运算符声明为类的成员函数,双目运算符声明成类的友元函数。
四、自增(++)、自减(--)运算符的重载
例:实现对复数对象实部的自增
Complex operator++(Complex& c1) //前置自增
{ return ++c1._real;}
Complex operator++(int)(Complex& c1) //后置自增
{ return c1._real++;}
C++中规定,后置自增的函数名要加(int)用于区分,后置自减也一样。
五、重载流插入运算符(<<)和重载流提取运算符(>>)
1、流插入运算符(<<)
例:重载流插入运算符,实现复数对象的输出
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
Complex(
double
real = 0,
double imag
= 0) :_real(real
)
, _imag(
imag)
[align=left] {[/align]
[align=left] }[/align]
ostream& operator<<(ostream
&
os)
//“<<”的重载
[align=left] {[/align]
os
<< "("
<< _real << ","
<< _imag <<
"i" <<
")" ;
return
os ;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1(2.3, 3.5);
[align=left] c1 << cout; [/align]
system(
"pause");
return
0;
[align=left]}[/align]
[align=left]
[/align]
请注意,上面红色的语句并没有错,这是因为重载流插入运算符函数是类成员函数,所以第一个参数是隐含的this指针。因为cout是输出流ostream类的对象。其中os就是cout。
为了解决上面红色语句不能连续输出和不符合正常逻辑的问题,我们一般将流插入运算符重载函数声明为类的友元函数,将ostream类对象和Complex类对象进行传参:
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
Complex(
double
real = 0,
double imag
= 0) :_real(real
)
, _imag(
imag)
[align=left] {[/align]
[align=left] }[/align]
friend
ostream & operator<<(ostream& os,
Complex& c)
//“<<”的重载
[align=left] {[/align]
os <<
"("
<< c._real << ","
<< c._imag <<
"i" <<
")";
return
os;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1(2.3, 3.5);
[align=left] cout << c1 << endl;[/align]
system(
"pause");
return
0;
[align=left]}[/align]
2、同流插入运算符重载一样,流提取运算符也是同样的道理
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
friend
istream & operator>>(istream& is,
Complex& c)
//“<<”的重载
[align=left] {[/align]
[align=left] is >> c._real >> c._imag;[/align]
return
is;
[align=left] }[/align]
friend
ostream & operator<<(ostream& os,
Complex& c)
//“<<”的重载
[align=left] {[/align]
os <<
"("
<< c._real << ","
<< c._imag <<
"i" <<
")";
return
os;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1;
[align=left] cin >> c1;[/align]
[align=left] cout << c1 << endl;[/align]
system(
"pause");
return
0;
[align=left]}[/align]
3、总结
istream& operator>>(istream &,自定义类 &);
ostream& operator<<(ostream &,自定义类 &);
我们知道函数重载就是对已有的函数赋予新的含义,使之实现新的功能。因此,同一个函数可以实现不同的功能,也就是一名多用。
运算符也可以重载,像我们平时使用的+运算符,对整形,单精度浮点型,双精度浮点型都能实现加法运算。又如,<<(左移),在输出操作中与流对象cout配合使用实现输出操作。>>(右移),在输入操作中与流对象cin配合使用实现输入操作。
在C++程序中,用户不能直接用C++提供的运算符来实现用户自定义类的运算,所以用户必须根据自己的需要对C++提供的运算符进行重载,赋予他们新的含义。
二、运算符重载的方法
运算符重载的方法是定义一个重载运算符函数,在需要执行被重载的运算符时,系统自动调用该函数。所以运算符重载实际上是函数的重载。
重载运算符的函数格式如下:
函数类型 operator 运算符名称(形参列表)
{对运算符的重载处理}
例:实现一个复数类,并重载+运算符
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
Complex(
double
real =0,
double imag=0) :_real(real
)
//构造函数
, _imag(
imag)
[align=left] {[/align]
[align=left] }[/align]
Complex
operator+(Complex
c2)
//对+运算符重载,使之能进行复数相加
[align=left] {[/align]
return
Complex (_real+c2._real,_imag+
c2._imag);
[align=left] }[/align]
void
display()
//打印函数
[align=left] {[/align]
cout <<
"("
<< _real << ","
<< _imag <<
"i" <<
")" << endl;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1(2.3,4.1);
Complex
c2(1.4, 2.8);
Complex
c3;
system(
"pause");
return
0;
[align=left]}[/align]
在上面的函数中,实现了+运算符重载,使+能够进行复数对象之间的运算。值得注意的是,运算符在被重载后,其原有的功能仍然保留。
三、运算符重载的规则
1、C++不允许用户自己定义新的运算符,只能对已有的运算符进行重载。
2、C++中不能重载的运算符只有五个,剩下的都可以重载
.(成员访问运算符)
.*(成员指针访问运算符)
::(作用域解析符)
sizeof(长度运算符)
?:(条件运算符)
3、重载不能改变运算符运算对象的个数(即操作数的个数)
4、重载不改变运算符的优先级别
5、重载不改变运算符的结合性
6、重载的运算符必须和用户自定义的自定义类型的对象一起使用,其参数至少应该有一个是类对象(或类的引用),防止用户修改用于标准类型数据的运算符的性质,比如下面这样
int operator+(int a,int b)
{ return a-b;}
会产生二义性。
7、用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载,类默认生成的。
8、一般将单目运算符声明为类的成员函数,双目运算符声明成类的友元函数。
四、自增(++)、自减(--)运算符的重载
例:实现对复数对象实部的自增
Complex operator++(Complex& c1) //前置自增
{ return ++c1._real;}
Complex operator++(int)(Complex& c1) //后置自增
{ return c1._real++;}
C++中规定,后置自增的函数名要加(int)用于区分,后置自减也一样。
五、重载流插入运算符(<<)和重载流提取运算符(>>)
1、流插入运算符(<<)
例:重载流插入运算符,实现复数对象的输出
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
Complex(
double
real = 0,
double imag
= 0) :_real(real
)
, _imag(
imag)
[align=left] {[/align]
[align=left] }[/align]
ostream& operator<<(ostream
&
os)
//“<<”的重载
[align=left] {[/align]
os
<< "("
<< _real << ","
<< _imag <<
"i" <<
")" ;
return
os ;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1(2.3, 3.5);
[align=left] c1 << cout; [/align]
system(
"pause");
return
0;
[align=left]}[/align]
[align=left]
[/align]
请注意,上面红色的语句并没有错,这是因为重载流插入运算符函数是类成员函数,所以第一个参数是隐含的this指针。因为cout是输出流ostream类的对象。其中os就是cout。
为了解决上面红色语句不能连续输出和不符合正常逻辑的问题,我们一般将流插入运算符重载函数声明为类的友元函数,将ostream类对象和Complex类对象进行传参:
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
Complex(
double
real = 0,
double imag
= 0) :_real(real
)
, _imag(
imag)
[align=left] {[/align]
[align=left] }[/align]
friend
ostream & operator<<(ostream& os,
Complex& c)
//“<<”的重载
[align=left] {[/align]
os <<
"("
<< c._real << ","
<< c._imag <<
"i" <<
")";
return
os;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1(2.3, 3.5);
[align=left] cout << c1 << endl;[/align]
system(
"pause");
return
0;
[align=left]}[/align]
2、同流插入运算符重载一样,流提取运算符也是同样的道理
class
Complex
[align=left]{[/align]
[align=left]public:[/align]
friend
istream & operator>>(istream& is,
Complex& c)
//“<<”的重载
[align=left] {[/align]
[align=left] is >> c._real >> c._imag;[/align]
return
is;
[align=left] }[/align]
friend
ostream & operator<<(ostream& os,
Complex& c)
//“<<”的重载
[align=left] {[/align]
os <<
"("
<< c._real << ","
<< c._imag <<
"i" <<
")";
return
os;
[align=left] }[/align]
[align=left]private:[/align]
double
_real;
double
_imag;
[align=left]};[/align]
[align=left]
[/align]
int
main()
[align=left]{[/align]
Complex
c1;
[align=left] cin >> c1;[/align]
[align=left] cout << c1 << endl;[/align]
system(
"pause");
return
0;
[align=left]}[/align]
3、总结
istream& operator>>(istream &,自定义类 &);
ostream& operator<<(ostream &,自定义类 &);
相关文章推荐
- Memcache[3]telnet操作Memcached
- Java 串口通信
- map管理成员函数指针
- angular的脏检查
- 小记——内存映射
- spark操作mysql数据库
- “区块链”将重新定义人类生活,你会看懂么?
- netdevgirl.eclipse创建maven javaweb项目
- Postfix邮件服务器搭建及配置
- python命令行下tab键补全命令
- javascript面试题:如何把一句英文每个单词首字母大写?
- Debain安装字体,修改默认编码,命令行
- hadoop伪分布式2.4.1安装
- ""和null的区别
- leetcode 262. Trips and Users
- BottomSheetDialog
- nginx生产环境常用功能include 、虚拟主机别名、rewrite、nginx status详细解析、fastcgi、访问控制
- RedHat Linux 手动设置IP及传送文件到远程主机
- git 操作
- eclipse里面已经提交的svn提交