[关闭]
@cxm-2016 2016-09-05T15:21:49.000000Z 字数 2386 阅读 1653

C++:运算符重载

c++ no
作者:陈小默


当我们学习C++的时候,一定接触过cout对象,你一定好奇过为什么左移运算符在这里就成了插入运算符了呢?所以这一节我们就来介绍一下吊炸天的C++运算符重载机制。

运算符重载规则

  1. operatorOP(argument-list)

重载运算符使用了被称作运算符函数的特殊函数形式。其中OP代表有效的C++运算符,也就是说只能使用C++中已有的运算符,因为重载的意思就是给已有的运算符赋予新的意义。像C++并不存在@运算符,理所当然我们也就不能重载@了。

自定义时间运算

这里我们定义一个表示时间的类,时间的内部实现是一个long long类型的数据。
我们需要这个时间类能具有设置和显示两个功能。并且还能自定义运算符,下面为time.h头文件内容

  1. #ifndef primer_time_h
  2. #define primer_time_h
  3. #include<string>
  4. class Time{
  5. private:
  6. enum {SECOND=1000,MINUTE=60*1000,HOURS=60*60*1000};
  7. long long time;
  8. public:
  9. void setMinutes(int m);
  10. void setHours(int h);
  11. void setSecondes(int s);
  12. long long getLongTime();
  13. Time operator+(Time t);
  14. Time operator-(Time t);
  15. Time operator*(int n);
  16. Time operator/(int n);
  17. void toString();
  18. };
  19. #endif

在声明中,我们定义了秒、分钟、小时的单位毫秒数常量。还有一个用来存储时间的long long类型的time。下面的toString方法用来打印时间,另外我们还重载了时间的加减乘除四个运算符。
下面看具体实现

  1. #include "stdafx.h"
  2. #include "time.h"
  3. void Time::setHours(int h){
  4. if(h>=0)time = time%HOURS+h*HOURS;
  5. }
  6. void Time::setMinutes(int m){
  7. if(m>=0&&m<60)time = (time-time%HOURS)+time%MINUTE+m*MINUTE;
  8. }
  9. void Time::setSecondes(int s){
  10. if (s>=0&&s<60)time = (time-time%MINUTE)+s*SECOND;
  11. }
  12. long long Time::getLongTime(){
  13. return time;
  14. }
  15. void Time::toString(){
  16. int hours = int(time/HOURS);
  17. int minutes = int((time%HOURS)/MINUTE);
  18. int seconds = int(time%MINUTE/SECOND);
  19. cout<<"Time["<<hours<<":"<<minutes<<":"<<seconds<<"]"<<endl;
  20. }
  21. Time Time::operator+(Time t){
  22. time+=t.getLongTime();
  23. return *this;
  24. }
  25. Time Time::operator-(Time t){
  26. time-=t.getLongTime();
  27. return *this;
  28. }
  29. Time Time::operator*(int n){
  30. time*=n;
  31. return *this;
  32. }
  33. Time Time::operator/(int n){
  34. time/=n;
  35. return *this;
  36. }

重载运算符的两种使用方式

第一种,函数调用形式

  1. time3 = time1.operator+(time2);

第二种,就是我们想要的运算符表示法

  1. time = time1 + time2;

多个重载运算符的连续运算

如果我们将表达式写成如下这种形式,能不能正常运行呢?

  1. time = time1 + time2 + time3;

想要回答这个问题,就要看这个表达式如何被转换为函数调用形式。在C++语法规则中+是自左向右结合的运算符。所以上述语句会被转化为如下形式

  1. time = time1.operator+(time2 + time3);

而括号内又可以转换,于是得到最终结果

  1. time = time1.operator+(time2.operator+(time3));

重载限制

1,重载后的操作符必须有一个操作数是用户类型,因为如果我们随意更改基本类型的操作符,那么程序将变得无法阅读。比如用户在声明中定义了如下方法

  1. double double::operator+(double d){
  2. return *this-d;
  3. }

那么我们在程序中看到的3.0+1.0的结果又是什么呢?
2,使用运算符时不能违反原有的句法规则。例如,不能将一个运算符重载为操作数。

  1. int x;
  2. % x;//invalid

3,不能创建新的运算符,只能使用已有的运算符。
4,不能重载以下运算符

符号 含义
sizeof 占用空间运算符
. 成员运算符
.* 成员指针运算符
:: 作用域解析符
?: 三元条件运算符
typeid RTTI运算符
const_cast 强制类型转换运算符
dynamic_cast 强制类型转换运算符
reinterpret_cast 强制类型转换运算符
static_cast 强制类型转换运算符

5,以下表中的运算符可以被重载

+ - * / % ^ & | ~=
! = < > += -+ *= /= %=
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- , ->* ->
() [] new delete new[] delete[]

6,上表中的下列运算符只能通过成员函数重载,其他的可以通过成员或者非成员函数进行重载

符号 含义
= 赋值运算符
() 函数调用运算符
[] 下标运算符
-> 指针成员访问运算符
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注