运算符重载
1. 运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同行为的发生。
2. 重载运算符
不能重载的算符
. :: .* ?:(条件运算符) sizeof(求字节数运算符)
可以重载的运算符
+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ‘ ->
[] () new delete new[] delete[]
3. 重载运算符的限制
不改变运算符的优先级
不改变运算符的结合性
不改变运算符所需要的操作数
不能创建新的运算符
注意:重载运算符不允许创造新的运算符,只能对已有的c++运算符进行重载。
重载运算符必须和用户定义的自定义类型的对象一起使用, 运算符函数的参数至少有一个必须是类的对象或者类的对象的引用
重载运算符不能改变运算符的运算对象(操作数)的个数,重载运算符的功能应类似于该运算符作用于标准类型数据时所实现的功能。
4. 重载运算符方式成员函数
成员运算符函数的原型在类的内部声明格式如下:
class X {
返回类型 operator运算符(形参表);
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
int & operator[](int i)
{
if( i > SIZE )
{
//当传入的index大于数组的长度,则返回第一个元素
return arr[0];
}
return arr[i];
}
};
双目运算符重载为成员函数
对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。
Complex Complex:: operator + (Complex &c2)
return Complex(real+c2.real, imag+c2.imag);}
一般而言,如果在类X中采用成员函数重载双目运算符@,成员运算符函数operator@ 所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象,则以下两种函数调用方法是等价的:
aa @ bb; // 隐式调用
aa.operator@(bb); // 显式调用
单目运算符重载为成员函数
对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。
Time Time∷operator++( ) //定义前置自增运算符“++”重载函数
{
if(++sec>=60) {
sec-=60; //满60秒进1分钟
++minute;
}
return *this; //返回当前对象值
}
Time Time∷operator++(int) //定义后置自增运算符“++”重载函数
{
Time temp(*this);
sec++;
if(sec>=60) {
sec-=60;
++minute;
}
return temp; //返回的是自加前的对象
}
5. 重载运算符方式友元函数
在第一个参数需要隐式转换的情形下,使用友元函数重载
运算符是正确的选择
友元函数没有 this 指针,所需操作数都必须在参数表显式
声明,很容易实现类型的隐式转换
C++中不能用友元函数重载的运算符有
= () [] ->
class Complex
{ public:
Complex( doubler =0, double i =0 ) { Real = r ; Image= i ; }
Complex(int a){ Real = a ; Image = 0 ; }
void print()const ;
friend Complexoperator+ ( const Complex & c1, const Complex & c2 ) ;
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 ) ;
}
注意:成员函数和友元函数的区别
成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
典型运算符重载
1. ++和—前置和后置
前置
成员函数 重载 A :: A operator++ () ;
解释为: Aobject . operator ++( );
友元函数 重载 friend A operator++ (A &) ;
解释为: operator ++( Aobject ) ;
后置
成员函数 重载 A :: A operator++ (int) ;
解释为: Aobject . operator ++( 0) ;
友元函数 重载: friend A operator++ (A &, int) ;
解释为: operator++(Aobject, 0)
public :
Increase ( ) { value=0; }
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; }
友元函数
public :
Increase ( ) { value=0; }
friend Increase operator ++ ( Increase & ) ; //前置
friend Increase operator ++ ( Increase &, int ) ; // 后置
private: unsigned value ;
};
Increase operator ++ (Increase & a )
{ a.value ++ ; return a ; }
Increase operator ++ (Increase & a, int )
{ Increase temp(a); a.value ++ ; return temp; }
运算符 [] 和 () 是二元运算符
注意:[]和 () 只能用成员函数重载,不能用友元函数重载
[] 运算符用于访问数据对象的元素
int & operator [ ] (int i ) { return v [ i ] ; }
() 运算符用于函数调用
设 x 是类 X 的一个对象,则表达式
x ( arg1, arg2, …)
可被解释为
x . operator ()(arg1, arg2, … )
如:
{ public :
double operator ( ) ( double x , double y ) ;
} ;
double F :: operator ( ) ( double x , double y )
{ return x * x + y * y ; }
重载流插入和流提取运算符
istream 和 ostream 是C++ 的预定义流类
cin 是 istream 的对象,cout是 ostream 的对象
运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
istream& operator>>(istream& in,class_name& obj)
{
in>>obj.item1;
in>>obj.item2;
. . .
in>>obj.itemn;
return in;
}
运算符重载是一个很方便的工具,面对不同的数据类型,或是许多数据类型结合的复杂数据类型,想要对它们进行操作,可以在已有运算符的前提下自定义扩充运算符含义,从而简化了代码的复杂程度,使其更直观,便于调用。到现在我已经对于重载运算符有了一定的认识,但是在运用的情况下,还是有点错误,在定义运算符含义时也有点不准,在以后的练习中多注意这方面的练习。