C++ 运算符重载
当运算符被用于类类型的对象时,C++允许我们为其指定新的含义;同时我们也能自定义类类型之间的转换规则。
运算符重载
运算符函数与普通函数相同,唯一的区别时运算符函数的名称为关键字operator + 运算符符号,同时我们不能重载内置类型的运算符,只能重载自定义类的运算符。
我们像调用普通函数一样调用运算符函数,例如:
data1+data2;//普通表达式
operator+(data1,data2);//等价函数调用表达式
data1+=data2;//基于“调用的表达式”
data1.operator+=(data2);//对成员运算符函数的等价调用
可以被重载的运算符包括:

而以下运算符无法重载:

运算符重载的基本格式为:
return_value classname::operator op(argument list)
{
/*..body..*/
}
重载运算符原型
根据不同类型的运算符,重载运算符函数的原型也不同:
- 考虑该运算符是否会修改算子,如果不会则argument list为const classname &,如果会argument list为classname &。
- 考虑返回类型return_value,基本上分为bool,const value 和reference三类。
根据以上规则将运算符原型大致分为下面几类:
- 算数运算符+ - * / % ^ & | ~
const T operator Op(const T & l,const T & r) const;//返回类型为常量,传入常量引用
- 关系运算符! && || < <= > >= == !=
bool operator Op(const T & l,const T & r) const;//返回类型为bool,传入常量引用
或者
bool operator Op(const T & ) const;
- 下标运算符[]
T & operator[](int index);//返回类型为引用可作为左值,传入index角标
- 递增递减运算符++ --
class A{
public:
/*...*/
//对于++、--运算符比较特殊,因为根据在对象前后不同效果不同
const A & operator ++();// prefix++,即++在对象前面
const A operator ++(int );// postfix++,即++在对象后面,此处int仅为重载区分
const A & operator --();// prefix--
const A operator --(int );// postfix--
/*...*/
}
- (复合)赋值运算符=、+= 、-= ...
T & operator Op(const T & ) ;// 为了与内置类型(复合)赋值运算符保持一致,返回其左侧运算对象引用
- 输入输出运算符<< 、>>
//与iostream标准库兼容的输入输出运算符必须是普通的非成员函数,而不能是类的成员函数
ostream & operator<<(ostream &os,const T & item)
{
/*body*/
/*
os<< /*...*/
*/
return os;
}
istream & operator>>(istream &is,T &item)
{
/*body*/
/*
is>> /*...*/
if(is)//输入运算符要处理输入失败的情况,而输出不需要
/*...*/
else
/*...*/
*/
return is;
}
T data;
cin >> data;
cout << data;
选择作为成员函数还是非成员函数
运算符重载函数不仅可以作为类的成员函数,还可以作为非成员函数,作为类的友元函数。
class A{
public:
/*...*/
friend const A operator+(const A &l,const A &r);
/*...*/
}
const A operator-(const A &l,const A &r){
/*...*/
}
一般而言有以下规则:
- 会改变对象本身的运算符或与给定类型密切相关的运算符通常为成员函数,例如++,--,*。
- 赋值= 、下表[]、调用()、成员访问箭头->必须为成员函数。
- 复合赋值运算符一般也重载为成员函数,但并不是必须的。
- 满足交换律(具有对称性)的运算符一般声明为非成员函数,这对混合类型的表达式有好处(例如int+double和double+int,我们希望他们的结果是一致的)
自定义Int类
class Int{
private:
int i;
public:
Int():i(0){}
Int(int j){i=j;}
const Int operator+(const Int &) const;
const Int operator-(const Int &) const;
Int & operator=(const Int &);
Int & operator+=(const Int &);
Int & operator-=(const Int &);
const Int& operator++();
const Int operator++(int );
const Int& operator--();
const Int operator--(int );
bool operator <(const Int &) const;
bool operator ==(const Int &) const;
bool operator !=(const Int &) const;
bool operator >(const Int &) const;
bool operator >=(const Int &) const;
bool operator <=(const Int &) const;
};
const Int Int::operator+(const Int &that) const{
Int tmp(i+that.i);
return tmp;
}
const Int Int::operator-(const Int &that) const{
Int tmp(i-that.i);
return tmp;
}
Int & Int::operator=(const Int &that){
if(this!=&that){
this->i=that.i;
}
return *this;
}
Int & Int::operator+=(const Int &that){
this->i+=that.i;
return *this;
}
Int & Int::operator-=(const Int &that){
this->i+=that.i;
return *this;
}
const Int& Int::operator++(){
*this =*this+1;
return *this;
}
const Int Int::operator++(int){
Int old(*this); //拷贝构造
++(*this); //调用const Int& Int::operator++()
return old;
}
const Int& Int::operator--(){
*this =*this-1;
return *this;
}
const Int Int::operator--(int){
Int old(*this); //拷贝构造
--(*this); //调用const Int& Int::operator--()
return old;
}
bool Int::operator <(const Int &that) const{
if(this->i<that.i)
return true;
return false;
}
bool Int::operator ==(const Int &that) const{
if(this->i==that.i)
return true;
return false;
}
bool Int::operator !=(const Int &that) const{
return !(*this==that);//只使用==和<来定义其他比较符号,一方面方便修改,另一方面编译器会自动内联不影响使用效率
}
bool Int::operator >(const Int &that) const{
return (!(*this<that))&&!(!(*this==that));
}
bool Int::operator >=(const Int &that) const{
return (!(*this<that));
}
bool Int::operator <=(const Int &that) const{
return (*this<that)||(*this==that);
}

浙公网安备 33010602011771号