一、心得总结
运算符重载使得用户自定义的数据以一种更简洁的方式工作。例如在做ATM模拟系统时,使用重载“<”来比较时间,可以简化程序,减少代码。另外,我们也可以重载运算符函数,将运算符用于操作自定义的数据类型。重载运算符函数可以对运算符做出新的解释,即定义用户所需要的各种操作。但运算符重载后,原有的基本语义不变,包括:不改变运算符的优先级,不改变运算符的结合性,不改变运算符所需要的操作数,不能创建新的运算符。优先级和结合性主要体现在重载运算符的使用上,而操作数的个数不但体现在重载运算符的使用上,更关系到函数定义时的参数设定。例如,一元运算符重载函数不能有两个参数,调用时也不能作用于两个对象。不能创建新的运算符,只有系统预定义的运算符才能被重载。
STL是C++标准程序库的核心,深刻影响了标准程序库的整体结构。
C++语言中大部分预定义的运算符都可以被重载。下列是可以重载的运算符:
+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> <<= == != <= >= && || ++ -- ->* ' -> [] () new delete
一下运算符不能被重载:
. .* :: ?; sizepf
二、内容总结及实例分析
&1运算符重载
1.1重载运算符的语法形式
运算符函数是一种特殊的成员函数或友元函数。成员函数的语句格式为:
类型 类名::operator op(参数表)
{
// 相对于该类定义的操作
}
其中,“类型”是函数的返回类型。“类名”是要重载该运算符的类。“op”表示要重载的运算符。函数名是"operator op",由关键字operator和被重载的运算符op组成。“参数表”列出该运算符所需要的操作数。
1.2用成员或友元函数重载运算符
1.一元运算符
一元运算符不论前置或后置,都要求有一个操作数:
Object op 或 op Object
当重载为成员函数时,编译器解释为:
Object.operator op()
函数operator op所需的操作数由对象Object通过this指针隐含传递,所以参数表为空。
当重载为友元函数时,编译器解释为:
operator op(Object)
函数operator op所需的操作数由参数表的参数Object提供。
2.二元运算符
任何二元运算符都要求有左、右操作数:
当重载为成员函数时,编译器解释为:
Object.operator op(ObjectR)
左操作数由对象OpbjectL通过this指针传递,右操作数由参数ObjectR传递。
重载为友元函数时,编译器解释为:
operator op(Object.ObjectR)
左、右操作数都由参数传递。
不管是成员函数还是友元函数重载,运算符的使用方法都相同。但由于它们传递参数的方法不同,因此导致实现的代码不同,应用场合不同。
1.2.1用成员函数重载运算符
当一元运算符的操作数,或者二元运算符的左操作数是该类的一个对象是,重载运算符函数一般定义为成员函数。
成员运算符函数的原型在类的内部声明格式如下:
class X
{
//...
返回类型operaor运算符(形参表);
//...
}
再类外定义成员运算符函数的格式如下:
返回类型X::operator运算符(形参表)
{
函数体
}
1.2.2.双目运算符重载为成员函数
对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。
例:
#include<bits/stdc++.h>
class complex{
public:
complex(){real=0,imag=0;}
private:
double real;
double imag;
};
complex(double r,double i){real=r;imap=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<<"c1+c2=";c3.diaplay();
return 0;
}
一般而言,如果在类X中采用成员函数重载双目运算符@,成员运算符函数operator@所需的一个操作数由对象aa通过this指针隐含地传递,它的另一个操作数bb在参数表中显示,aa和bb是类X的两个对象,则以下两种函数调用方法是等价的:
aa@bb;//隐式调用
aa.operator@(bb);//显式调用
1.2.3单目运算符重载为成员函数
对单目运算符而言,成员函数运算符函数的参数表中没有参数,此时当前对象作为运算符的一个操作数。
有一个Time类,包含数据成员minute(分)和(秒),模拟秒表,每次走一秒,满60进一分钟,此时秒又从0开始算。要求输出分和秒的值。
class time
{
public:
Time(){minute=0;sec=0;}
Time(int m,int s):minute(m),sec(s){}
Time operator++(); //声明前置自增运算符"++"重载函数
Time operator++(int); //声明后置自增运算符“++”重载函数
private:
int minute;
int sec;
};
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; //返回的是自加前的对象
}
}
1.2.4.用友元函数重载运算符
友元函数重载运算符常用于运算符的左右操作数类型不同的情况
<1>.在第一个参数需要隐式转换的情形下,使用友元函数重载
<2>.友元函数没有this指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
<3>.C++中不能用友元函数重载的运算符有= () [] ->
成员函数运算符函数与友元运算符函数的比较
(1)成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。
(2)双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。
1.3几个典型运算符重载
1.3