运算符重载就是赋予运算符新的功能,使其能够用来操作对象
成员函数重载运算符格式:
类内声明:返回类型 operator运算符(形参表);
类外定义:返回类型 X::operator运算符(形参表)
{
函数体
}
重载运算符的限制
1.不能重载的算符
. :: .* ?: sizeof
2.可以重载的运算符
+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ‘ ->
[] () new delete new[] delete[]
3.运算符原有基本语义不变:
不改变运算符的优先级
不改变运算符的结合性
不改变运算符所需要的操作数
不能创建新的运算符
一. 用成员或友元函数重载运算符
1.一元运算符与二元运算符
| 一元运算符 | 二元运算符 |
| Object op 或 op Object
| ObjectL op ObjectR
|
重载为成员函数 | Object . operator op () | ObjectL . operator op ( ObjectR ) |
操作数由对象Object通过this指针隐含传递
| 左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递 | |
重载为友元函数 | operator op (Object)
| operator op ( ObjectL, ObjectR )
|
操作数由参数表的参数Object提供 | 左右操作数都由参数传递 |
2.双目运算符与单目运算符重载为成员函数
| 双目运算符 | 单目运算符 |
| 成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。
| 成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数 |
等价的两种函数调用方法 | aa@bb; // 隐式调用 aa.operator @(bb); // 显式调用 | @aa; // 隐式调用 aa.operator@(); // 显式调用 |
| 成员运算符函数operator@ 所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象 | 成员运算符函数operator @所需的一个操作数由对象aa通过this指针隐含地传递。因此,在它的参数表中没有参数 |
3.用友元函数重载
注:
1)友元函数重载运算符常用于运算符的左右操作数类型不同的情况
2)在第一个参数需要隐式转换的情形下,使用友元函数重载运算符
3)友元函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
4)C++中不能用友元函数重载的运算符有
= () [] ->
4.成员运算符函数与友元运算符函数的比较
(1) 成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。
(2) 双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数
5.几个典型运算符重载
设 A Aobject ;
运算符 ++和 - - 有两种方式:
前置方式: ++Aobject --Aobject
成员函数 重载 A ::A operator++ () ;
解释为: Aobject .operator ++( ) ;
友元函数 重载 friendA operator++ (A &) ;
解释为: operator ++(Aobject ) ;
后置方式: Aobject ++ Aobject --
成员函数 重载 A ::A operator++ (int) ;
解释为: Aobject .operator ++( 0 ) ;
友元函数 重载: friendA operator++ (A &, int) ;
解释为: operator++(Aobject,0)
三.重载运算符的具体使用
1. 重载赋值运算符 =
operator=必须重载为成员函数
重载函数原型为:
类名 & 类名 :: operator= ( 类名 ) ;
2. 重载运算符[]和()
运算符 [] 和 () 是二元运算符
[] 和 () 只能用成员函数重载,不能用友元函数重载
| 重载下标运算符 [] | 重载函数调用符 () |
| [] 运算符用于访问数据对象的元素
| () 运算符用于函数调用
|
重载格式 | 类型 类 :: operator[] ( 类型 ) ;
| 类型 类 :: operator() ( 参数表 ) ;
|
3. 重载流插入和流提取运算符
istream 和 ostream 是 C++ 的预定义流类
| istream | ostream |
对象 | cin | cout |
| 运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
| 运算符 << 由ostream 重载为插入操作,用于输出基本类型数据 |
| 只能被重载成友元函数,不能重载成成员函数 | |
定义输入运算符函数 重载函数的一般格式 | ostream&operator<<(ostream& out,class_name& obj) { out<<obj.item1; out<<obj.item2; .. . out<<obj.itemn; return out; }
| istream&operator>>(istream& in,class_name& obj) { in>>obj.item1; in>>obj.item2; . . . in>>obj.itemn; return in; }
|
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型 |
例题
1. 复数
#include<bits/stdc++.h>
using namespace std;
class Complex
{ public:
Complex( double r =0, double i =0 ) { Real = r ; Image = i ; }
Complex(int a) { Real = a ; Image = 0 ; }
void print() const ;
friend Complex operator+ ( const Complex & c1, const Complex & c2 ) ;
friend Complex operator- ( const Complex & c1, const Complex & c2 ) ;
friend Complex operator- ( const Complex & c ) ;
private:
double Real, Image ;
};
Complex operator + ( const Complex & c1, const Complex & c2 )
{ double r = c1.Real + c2.Real ; double i = c1.Image+c2.Image ;
return Complex ( r, i ) ;
}
Complex operator - ( const Complex & c1, const Complex & c2 )
{ double r = c1.Real - c2.Real ; double i = c1.Image - c2.Image ;
return Complex ( r, i ) ;
}
Complex operator- ( const Complex & c )
{ return Complex ( -c.Real, - c.Image ) ; }
void Complex :: print() const
{ cout << '(' << Real << " , " << Image << ')' << endl ; }
2.友元函数重载++
#include<iostream>
using namespace std;
class Increase
{ public :
Increase ( ) { value=0; }
void display( ) const { cout<<value<<'\n'; } ;
Increase operator ++ ( ) ; // 前置
Increase operator ++ ( int ) ; // 后置
private: unsigned value ;
};
Increase Increase :: operator ++ ( )
{ value ++ ; return *this ; }
Increase Increase :: operator ++ ( int )
{ Increase temp; temp.value = value ++ ; return temp; }
int main( )
{ Increase a , b , n ; int i ;
for ( i = 0 ; i < 10 ; i ++ ) a = n ++ ;
cout <<"n= " ; n.display( ) ; cout <<"a= " ; a.display( ) ;
for ( i = 0 ; i < 10 ; i ++ ) b = ++ n ;
cout << "n= " ; n.display( ) ; cout << "b= " ; b.display( ) ;
}
3.
#include<iostream>
using namespace std;
class vector
{ public :
vector ( int n ) { v = new int [ n ] ; size = n ; }
~ vector ( ) { delete [ ] v ; size = 0 ; }
int & operator [ ] ( int i ) { return v [ i ] ; }
private :
int * v ; int size ;
};
int main ( )
{ vector a ( 5 ) ;
a [ 2 ] = 12 ;
cout << a [ 2 ] << endl ;
}
心得
重载运算符就是赋予运算符新的功能,使它能够解决更多的问题,从而使得程序更简洁,易懂,同时大大提高书写速度。