@cxm-2016
2016-09-05T15:21:49.000000Z
字数 2386
阅读 1629
c++
no
作者:陈小默
当我们学习C++的时候,一定接触过cout对象,你一定好奇过为什么左移运算符在这里就成了插入运算符了呢?所以这一节我们就来介绍一下吊炸天的C++运算符重载机制。
operatorOP(argument-list)
重载运算符使用了被称作运算符函数的特殊函数形式。其中OP代表有效的C++运算符,也就是说只能使用C++中已有的运算符,因为重载的意思就是给已有的运算符赋予新的意义。像C++并不存在@
运算符,理所当然我们也就不能重载@
了。
这里我们定义一个表示时间的类,时间的内部实现是一个long long类型的数据。
我们需要这个时间类能具有设置和显示两个功能。并且还能自定义运算符,下面为time.h
头文件内容
#ifndef primer_time_h
#define primer_time_h
#include<string>
class Time{
private:
enum {SECOND=1000,MINUTE=60*1000,HOURS=60*60*1000};
long long time;
public:
void setMinutes(int m);
void setHours(int h);
void setSecondes(int s);
long long getLongTime();
Time operator+(Time t);
Time operator-(Time t);
Time operator*(int n);
Time operator/(int n);
void toString();
};
#endif
在声明中,我们定义了秒、分钟、小时的单位毫秒数常量。还有一个用来存储时间的long long类型的time。下面的toString方法用来打印时间,另外我们还重载了时间的加减乘除四个运算符。
下面看具体实现
#include "stdafx.h"
#include "time.h"
void Time::setHours(int h){
if(h>=0)time = time%HOURS+h*HOURS;
}
void Time::setMinutes(int m){
if(m>=0&&m<60)time = (time-time%HOURS)+time%MINUTE+m*MINUTE;
}
void Time::setSecondes(int s){
if (s>=0&&s<60)time = (time-time%MINUTE)+s*SECOND;
}
long long Time::getLongTime(){
return time;
}
void Time::toString(){
int hours = int(time/HOURS);
int minutes = int((time%HOURS)/MINUTE);
int seconds = int(time%MINUTE/SECOND);
cout<<"Time["<<hours<<":"<<minutes<<":"<<seconds<<"]"<<endl;
}
Time Time::operator+(Time t){
time+=t.getLongTime();
return *this;
}
Time Time::operator-(Time t){
time-=t.getLongTime();
return *this;
}
Time Time::operator*(int n){
time*=n;
return *this;
}
Time Time::operator/(int n){
time/=n;
return *this;
}
第一种,函数调用形式
time3 = time1.operator+(time2);
第二种,就是我们想要的运算符表示法
time = time1 + time2;
如果我们将表达式写成如下这种形式,能不能正常运行呢?
time = time1 + time2 + time3;
想要回答这个问题,就要看这个表达式如何被转换为函数调用形式。在C++语法规则中+
是自左向右结合的运算符。所以上述语句会被转化为如下形式
time = time1.operator+(time2 + time3);
而括号内又可以转换,于是得到最终结果
time = time1.operator+(time2.operator+(time3));
1,重载后的操作符必须有一个操作数是用户类型,因为如果我们随意更改基本类型的操作符,那么程序将变得无法阅读。比如用户在声明中定义了如下方法
double double::operator+(double d){
return *this-d;
}
那么我们在程序中看到的3.0+1.0的结果又是什么呢?
2,使用运算符时不能违反原有的句法规则。例如,不能将一个运算符重载为操作数。
int x;
% x;//invalid
3,不能创建新的运算符,只能使用已有的运算符。
4,不能重载以下运算符
符号 | 含义 |
---|---|
sizeof | 占用空间运算符 |
. | 成员运算符 |
.* | 成员指针运算符 |
:: | 作用域解析符 |
?: | 三元条件运算符 |
typeid | RTTI运算符 |
const_cast | 强制类型转换运算符 |
dynamic_cast | 强制类型转换运算符 |
reinterpret_cast | 强制类型转换运算符 |
static_cast | 强制类型转换运算符 |
5,以下表中的运算符可以被重载
+ | - | * | / | % | ^ | & | | | ~= |
! | = | < | > | += | -+ | *= | /= | %= |
^= | &= | |= | << | >> | >>= | <<= | == | != |
<= | >= | && | || | ++ | -- | , | ->* | -> |
() | [] | new | delete | new[] | delete[] |
6,上表中的下列运算符只能通过成员函数重载,其他的可以通过成员或者非成员函数进行重载
符号 | 含义 |
---|---|
= | 赋值运算符 |
() | 函数调用运算符 |
[] | 下标运算符 |
-> | 指针成员访问运算符 |