一、运算符重载规则
1、重载运算符的限制
以下运算符不能被重载:
. :: .* ?: sizeof
可以重载的运算符:
+ - * / % ^ & | ~
! = < > += -= *= /= %=
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ' ->
[] () new delete
重载运算符函数可以对运算符作出新的解释,但原有基本语义不变:
(1)不改变运算符的优先级
(2)不改变运算符的结合性
(3)不改变运算符所需要的操作数
(4)不能创建新的运算符
2、重载运算符的语法形式
运算符函数是一种特殊的成员函数或友元函数。成员函数的语句格式为:
类型 类名::operator op(参数表)
{
//相对于该运算符的操作
}
二、用成员或友元函数重载运算符
1、一元运算符
一元运算符不论前置或后置,都要求有一个操作数:
Object op 或 op Object
当重载为成员函数时,编译器解释为:
Object.operator op()
当重载为友元函数时,编译器解释为:
operator op(Object)
2、二元运算符
任何二元运算符都要求有左、右操作数:
ObjectL.operator op(ObjectR)
重载为友元函数时,编译器解释为:
operator op(ObjectL,ObjectR)
3、用成员函数重载运算符
成员运算符函数的原型在类的内部声明格式如下:
class X
{
//...
返回类型 operator运算符(形参表);
//...
};
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
下面由复数运算重载“+”举例:
#include<bits/stdc++.h>
using namespace std;
class Complex
{
private:
double real;
double imag;
public:
Complex(){real=0;imag=0;}
Complex(double r,double i){real=r;imag=i;}
Complex operator+(Complex &c2);
void display();
};
Complex Complex::operator+(Complex &c2)
{
return Complex(real+c2.real,imag+c2.imag);
}
void Complex::display()
{
cout<<"("<<real<<","<<imag<<"i)"<<endl;
}
int main()
{
Complex c1(3,4),c2(5,-10),c3;
c3=c1+c2;
cout<<"c1=";c1.display();
cout<<"c2=";c2.display();
cout<<"c3=";c3.display();
return 0;
}
注:(1)一般而言,采用成员函数重载双目运算符时,以下两种方法是等价的:
aa@bb;//隐式调用
aa.operator@(bb);//显式调用
(2)对单目运算符而言,成员运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。
(3)一般而言,采用成员函数重载单目运算符时,以下两种方法是等价的:
@aa;
aa.operator@();
4、用友元函数重载运算符
友元函数重载运算符常用于运算符的左右操作数类型不同的情况。
例如复数运算:
#include<iostream>
using namespace std;
class Complex
{
double real,imag;
public:
Complex(double r=0,double i=0);
Complex(int a) //定义当只有一个参数时为实数
{
real=a;
imag=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); //一元运算
};
Complex::Complex(double r,double i)
{
real=r;imag=i;
}
Complex operator+(const Complex &c1,const Complex &c2)
{
double r=c1.real+c2.real;
double i=c1.imag+c2.imag;
return Complex(r,i);
}
Complex operator-(const Complex &c1,const Complex &c2)
{
double r=c1.real-c2.real;
double i=c1.imag-c2.imag;
return Complex(r,i);
}
Complex operator-(const Complex &c)
{
return Complex(-c.real,-c.imag);
}
void Complex::print()const
{
cout<<'('<<real<<","<<imag<<')'<<endl;
}
int main()
{
Complex c1(2,3),c2(4,6);
Complex c;
c=c1-c2; //operator-(c1,c2)
c.print();
c=25+c2; //operator+(25,c2)
c.print();
c=c2+25; //operator+(c2,25)
c.print();
c=-c1; //operator-(c1)
c.print();
}
三、几个典型运算符的重载
1、重载++与--
(1)前置自增表达式
++Aobject
若用成员函数重载,则编译器解释为:Aobject.opeator++()
对应的函数原型为:A & A::operator++();
若用友元函数重载,则编译器解释为:operator++(Aobject)
对应的函数原型为:friend A & operator++(A &);
(2)后置自增表达式
Aobject++
成员函数重载的解释为:Aobject.operator++(0)
对应的函数原型为:A & A::operator++(int);
友元函数重载的解释为:operator++(Aobject,0)
对应的函数原型为:friend A & operator++(A &,int);
2、重载赋值运算符
赋值运算符重载用于对象数据的复制,只能用成员函数重载。重载函数原型为:
类名 & 类名::operator=(类名);
3、重载运算符[]和()
运算符[]和()是二元运算符;[]和()只能用成员函数重载,不能用友元函数重载。
4、重载流插入和流提取运算符
注:(1)istream和ostream是C++的预定义流类
(2)cin是istream的对象,cout是ostream的对象
(3)运算符<<由ostream重载为插入操作,用于输出基本类型数据
(4)运算符>>由istream重载为提取操作,用于输入基本类型数据
(5)用友元函数重载<<和>>,输出和输入用户自定义的数据类型