运算符重载
运算符重载的意义
对于普通的数据成员,c++已经重载了基本的运算符,但是对于一些我们自己设置的类和结构体的新类型,运算符的功能不能直接对他们进行操作,所以就需要我们对运算符惊醒重载,实际意思就是,赋予运算符新的功能让他们能够对我们自己定义的类和结构体进行操作。
重载运算符的限制
可以重载的运算符
+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ‘ ->
[] () new delete new[] delete[]
不能重载的算符
. :: .* ?: sizeof
重载运算符可以对运算符做出新的解释,己定义用户所需要的各种操作,但是运算符基本语义保持不变
l 不改变运算符的优先级;
l 不改变运算符的结合性
l 不改变运算符所需要的操作数
l 不能创建新的运算符
运算符重载的语法形式
成员函数重载
返回类型 operator op(运算符)(参数表)
{
//相对于该类定义的操作;
}
成员函数重载默认运算符左数据为类数据成员
友元函数重载
friend 返回类型 opeartor op(运算符)(参数表)
{
//相对于该类定义的操作
}
另,重载有赋值含义的运算符时有在opeartor 前面加& (引用)
对于赋值运算符和地址运算符系统提供默认默认重载版本
赋值运算符 = ,系统默认重载为对象数据成员的赋值
地址运算符 & ,系统默认重载为返回任何类对象的地址
例如:
#include <iostream>
using namespace std;
class Complex
{
public:
Complex()
{
real=0,imag=0;
}
Complex(double r,double i)
{
real=r;
imag=i;
}
Complex operator + (Complex &c2)
{
return Complex(real+c2.real,imag+c2.imag);
}
friend Complex operator -(Complex&c1,Complex &c2);
void display();
private:
double real;
double imag;
};
Complex operator -(Complex&c1,Complex &c2)
{
Complex c(c1.real-c2.real,c1.imag-c2.imag);
return c;
}
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<<"c1+c2 =";
c3.display( );
return 0;
}
一元运算符
运算符只对一个类对象进行操作,不论前置或者后置,都要求有且仅有一个操作数
对于成员函数数,操作对象有this指针隐含传递
对于友元函数们需要用形参表示
二元运算符
任何二元运算符都需要左,右两个操作数
成员函数左操作数右this指针隐含提供,右指针由参数表提供
友元函数左右操作数皆有参数表提供
由于成员函数重载和友元函数重载表达方式的不同,应用场合不同。
注:
赋值运算=,下标运算符 [],(),->,必须为成员函数
输入输出 << ,>>, 必须重载为友元函数
使用成员函数重载
成员函数存在this隐含指针,所以不需要所有操作数都用参数表提供
重载 ++
#include <iostream>
using namespace std;
class Time
{
public:
Time( )
{
minute=0;
sec=0;
}
Time(int m,int s):minute(m),sec(s) { }
Time operator++( ); //声明前置运算符 ++x
Time operator++(int); //声明后置运算符 x++
//此时后置运算符需要一个形参表示后置运算符,此形参没有实际意义
void display();
private:
int minute;
int sec;
};
Time Time::operator++( ) //定义前置自增运算符“++”重载函数
{
if(++sec>=60)
{
sec-=60; //满60秒进1分钟
++minute;
}
return *this; //返回当前对象值
}
TimeTime::operator++(int) //定义后置自增运算符“++”重载函数
{
Timetemp(*this);
sec++;
if(sec>=60)
{
sec-=60;
++minute;
}
return temp; //返回的是自加前的对象
}
void Time::display()
{
cout<<minute<<":"<<sec<<endl;
}
int main()
{
Time t1(1,58);
t1.display();
Time n;
n=t1++;
n.display();
t1.display();
Time t2(2,36);
t2.display();
n=++t2;
n.display();
t2.display();
return 0;
}
友元函数版
#include <iostream>
using namespace std;
class Time
{
public:
Time( )
{
minute=0;
sec=0;
}
Time(int m,int s):minute(m),sec(s) { }
friend Time operator++(Time &t ); //声明前置运算符 ++x
friend Time operator++(Time&t,int); //声明后置运算符 x++
//此时后置运算符需要一个形参表示后置运算符,此形参没有实际意义
void display();
private:
int minute;
int sec;
};
Time operator++(Time &t) //定义前置自增运算符“++”重载函数
{
if(++t.sec>=60)
{
t.sec-=60; //满60秒进1分钟
++t.minute;
}
return t; //返回当前对象值
}
Time operator++(Time &t,int) //定义后置自增运算符“++”重载函数
{
Time temp=t;;
t.sec++;
if(t.sec>=60)
{
t.sec-=60;
++t.minute;
}
return temp; //返回的是自加前的对象
}
void Time::display()
{
cout<<minute<<":"<<sec<<endl;
}
int main()
{
Time t1(1,58);
t1.display();
Time n;
n=t1++;
n.display();
t1.display();
Time t2(2,36);
t2.display();
n=++t2;
n.display();
t2.display();
return 0;
}
特殊运算符的重载
赋值运算符重载用于对象数据的复制
operator = 必须重载为成员函数
重载函数原型为:
类名 & operator= ( 类名 ) ;
运算符 [] 和 () 是二元运算符
[] 和 () 只能用成员函数重载,不能用友元函数重载
重载小括号
#include <iostream>
using namespace std ;
class F
{
public :
double operator ( ) ( double x, double y ) ;
} ;
double F :: operator ( ) ( double x, double y )
{
return x * x + y * y ;
}
int main ( )
{
F f ;
cout << f ( 5.2, 2.5 ) << endl;
}
重载输入输出符
istream 和 ostream 是 C++ 的预定义流类
cin 是 istream 的对象,cout 是 ostream 的对象
运算符 << 由ostream重载为插入操作,用于输出基本类型数据
运算符 >> 由istream 重载为提取操作,用于输入基本类型数据
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
定义输出运算符“<<”重载函数的一般格式如下:
ostream& operator <<(ostream& out,const 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;
}
样例:
#include <iostream>
using namespace std;
class Point
{
int x,y;
public:
friend istream & operator>>(istream & in, Point &p);
friend ostream & operator<<(ostream & out,const Point &p);
};
istream & operator>>(istream & in, Point &p)
{
cout<<"Please input apoint:"<<endl;
in>>p.x;
in>>p.y;
return in;
}
ostream &operator<<(ostream & out,const Point &p)
{
out<<"("<<p.x<< ","<<p.y <<")"<<endl;
return out;
}
int main()
{
Point p;
cin>>p;
cout<<p;
return 0;
}
心得体会
重载运算符的学习让我知道了许多东西并不能拘于一格,可以采用某些方法,让复杂的问题简单化。
运算符的重载让我们在类的编写上变得更加方便和美观。