操作符重载
重载操作符是具有特殊函数名的函数,关键字operator后面接需要定义的操作符符号。
操作符重载也是一个函数,具有返回值和形参表,它的形参数目与操作符的操作数目相同。
表示形式:
返回类型 operator 操作符(参数列表);
不能被重载的操作符:
.(成员选择符)、.*(成员对象选择符)、::(域解析操作符)、?:(条件操作符)
注意:
1.不能通过连接其他符号来创建新的操作符;
2.重载操作符必须有一个类类型或者枚举类型的操作数;
int operator +(const int _iNum1 ,const int _iNum2 ) //报错,operator必须至少一个类类型的形参
{
return( _iNum1 + _iNum2);
}
enum Test
{
one,
two,
three,
};
int operator+(const Test t1,constTest t2) //正确
{
returnt1+t2;
}
int main()
{
intret = 3+4;
return0;
}
3.用于内置类型的操作符,其含义不能改变,
4.不再具备短求值特性
重载操作符不能保证操作符的求值顺序,在重载&&和||中,对每个操作数都要进行求值,而且对操作符的 求值顺序不能规定,因此,重载&&和||和逗号操作符不是很好的做法。
5.作为类成员的重载函数,其形参看起来比操作数数目少一,
6.一般将算术操作符定义为非成员函数,将赋值运算符定义成成员函数,
7.操作符定义为非类的成员函数时,一般定义为类的友元,
8.==和!=操作符一般要成对重载,
9.下标操作符[]:一个非const成员并返回引用,一个是const成员并返回引用
10.解引用操作符*和->操作符,不显示任何操作符,
11. 自增自减操作符
前置式++/--必须返回被增量或则减量的引用
后缀式++/--必须返回旧值,并且应该是值返回而不是引用返回
12.输入操作符>>和输出操作符>>必须定义为类的友元函数,
以下为操作符的重载举例
复数类:
class Complex
{
public:
Complex(intreal = 1.0,int image = 1.0)
:_real(real)
,_image(image)
{}
Complex(constComplex & c)
{
_real= c._real;
_image= c._image;
}
~Complex()
{}
private:
double_real;
double_image;
};
符号=:
Complex & operator=(constComplex &c) //必须有返回值:支持连续赋值
{
if(this!= &c) //防止自己给自己赋值
{
_real= c._real;
_image= c._image;
}
return*this;
}
符号+:
Complex operator+(const Complex&c)
{
returnComplex(_real+c._real,_image+c._image);//返回无名对象,编译器自动优化,没有创建临时变量
}
符号-:
Complex operator-(const Complex&c)
{
returnComplex(_real-c._real,_image-c._image);//返回无名对象,编译器自动优化,没有创建临时变量
}
符号*:
Complex operator*(const Complex&c)
{
returnComplex(_real*c._real,_image*c._image);
}
符号/:
Complexoperator/(const Complex &c)
{
if((c._real!= 0)&&(c._image != 0))
{
returnComplex(_real/c._real,_image/c._image);
}
}
符号+=:
Complex& operator+=(const Complex &c)
{
_real= _real+c._real;
_image= _image+c._image;
return*this;
}
符号-=:
Complex & operator-=(constComplex &c)
{
_real= _real-c._real;
_image= _image-c._image;
return*this;
}
符号*=:
Complex & operator*=(constComplex &c)
{
_real= _real*c._real;
_image= _image*c._image;
return*this;
}
符号/=:
Complex & operator/=(constComplex &c)
{
if((c._real!= 0)&&(c._image != 0))
{
_real= _real/c._real;
_image= _image/c._image;
return*this;
}
}
符号==、!=、>=、<=:
bool operator==(const complex& c) //c1.operator==(c2)
{
/*if(_real== c._real && _image == c._image)
{
returntrue;
}
else
returnfalse;*/
return ((_real == c._real) &&(_image == c._image));
}
booloperator!=(const complex & c) //c1.operator!=(c2);
{
return((_real != c._real)&&(_image != c._image));
}
booloperator>(const complex &c)
{
return(_real>c._real);
}
booloperator<(const complex &c)
{
return(_real<c._real);
}
booloperator>=(const complex &c)
{
return((_real>c._real)||(_real==c._real));
}
booloperator<=(const complex &c)
{
return((_real<c._real)||(_real==c._real));
}
符号前置++,后置++,前置--,后置--,输出运算符
class Test
{
public:
Test(inta = 1)
:_a(a)
{}
Test(constTest &t)
{
_a= t._a;
}
Test& operator++() //前置加加
{
_a= _a+1;
return*this;
}
Testoperator++(int)//后置加加
{
Testtemp(*this);
_a= _a+1;
returntemp;
}
Test& operator--() //前置减减
{
_a= _a-1;
return*this;
}
Testoperator--(int)//后置减减
{
Testtemp(*this);
_a= _a-1;
returntemp;
}
//类的成员函数
ostream& operator<<(ostream &_cout) //t.opperator<<(cout)
{
_cout<<_a;
return_cout; //调用形式t1<<cout;
}
~Test()
{}
private:
int_a;
};
//不是类的成员函数
ostream & operator<<(ostream&_cout,const Test &t) //调用形式:cout<<t2;
{
_cout<<t._a; //公有成员
return_cout;
}
int main()
{
Testt1;
Testt2;
t1<<cout;
cout<<t1;
getchar();
return0;
}
友元
什么是友元函数?
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类中申 明,申明是需要加上friend关键字。
友元函数说明:
1.友元函数可访问类的私有成员,但不是类的成员函数;
2.友元函数不能用const修饰;
3.友元函数可以在类定义的任何地方声明,不受类访问限定符限制;
4.一个函数可以是多个类的友元函数;
5.友元函数的调用与普通函数的调用和原理相同。
class Time
{
public:
Time(inthour,int minute,int second)
:_hour(hour)
,_minute(minute)
,_second(second)
{}
friendvoid Display(Time &t);
private:
int_hour;
int_minute;
int_second;
};
void Display(Time &t)
{
cout<<t._hour<<":"<<t._minute<<":"<<t._second<<endl;
}
int main()
{
Timet1(1,2,3);
Display(t1);
getchar();
return0;
}
上例中display函数使用类的数据成员时,必须指定要访问的对象,因为display函数是Time类的友元函数,而不是成员函数,不能默认引用Time类的数据成员。
friend函数不仅可以是一般函数,还可以是另一个类的成员函数;
友元类
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员;
友元的优缺点
优点:提高了程序运行效率
缺点:破坏了类的封装性和隐藏性
注意 :
友元关系不能继承
友元关系是单向的,不具有交换性
友元关系不能传递