第11章 使用类——运算符重载(一)一个简单的运算符重载示例(Time类对象的加法)

本文章是作者根据史蒂芬·普拉达所著的《C++ Primer Plus》而整理出的读书笔记,如果您在浏览过程中发现了什么错误,烦请告知。另外,此书由浅入深,非常适合有C语言基础的人学习,感兴趣的朋友可以自行阅读此书籍。

运算符重载

我们先了解下函数重载的概念,函数重载,也叫函数多态,指的是用户可以定义多个名称相同但特征标(参数列表)不同的函数,函数重载可以用同名的函数来完成相同的基本操作,即使这种操作被用于不同的数据类型。

运算符重载也是一种形式的C++多态,它将重载的概念扩展到运算符上,允许赋予C++运算符多种含义。实际上,很多C++(包括C语言)运算符已经被重载。例如,将*运算符用于地址,将得到存储在这个地址中的值;但将它用于两个数字时,得到的将是它们的乘积。C++根据操作数的数目和类型来决定采用哪种操作。

C++允许将运算符重载扩展到用户定义的类型。例如,允许使用+将两个对象相加。编译器将根据操作数的数目和类型决定使用哪种加法定义。重载运算符可使代码看起来更自然。

运算符函数的格式如下:

operatorop(argument-list)

例如,operator+()重载+运算符,operator()重载运算符。op必须是有效的C++运算符,不能虚构一个新的符合。比如不能有operator@()这样的函数,因为C++中没有@运算符。

假设有一个Student类,我们为它定义了一个,operator+()成员函数,目的是将两个Student对象的总分相加。假设st1,st2,st3都是类对象,那么我们就可以这样写:

st3 = st1 + st2;

编译器发现,操作数是Student类对象,因此使用相应的运算符重载函数替换上述运算符:

st3 = st1.operator+(st2);

然后该函数隐式地使用st1(调用了方法),而显示地使用st2对象(被作为参数传递),来计算总和,并返回这个值。更重要的是,可以使用简单的+运算符表示法,而不必使用笨拙的函数表示法。

运算符重载示例,设计一个时间类

假设我们上午工作花了2小时35分钟,下午工作花了4小时40分钟,我们想要计算下总共花了多少时间,但要相加的单位与内置类型不匹配。因此我们可以实现一个Time类,使其可以进行两个时间的加法。

在使用运算符重载这个功能之前,我们先看看原始方法应该怎么做,我们需要定义一个求和的成员函数,可以对两个对象的小时和分钟分别求和,分钟如果大于60则小时+1。我们可以写出这样的类声明:

类声明如下:

//mytime0.hpp
#ifndef _MYTIME0_HPP_
#define _MYTIME0_HPP_
class Time
{
private:
  int hours;
  int minutes;
public:
  Time();
  Time(int h, int m = 0);
  void AddMin(int m);
  void AddHr(int h);
  void Reset(int h = 0, int m = 0);
  Time Sum(const Time& t) const;              //此成员函数返回一个Time类对象,因为加法的结果需要一个新的变量来接收,比如 a = b + c;
  void Show() const;
};
#endif

类方法实现如下:

//mytime0.cpp
#include <iostream>
#include "mytime0.hpp"

Time::Time()
{
  hours = minutes = 0;
}

Time::Time(int h, int m)
{
  hours = h;
  minutes = m;
}

void Time::AddMin(int m)
{
  int total_minutes  = minutes + m;
  minutes = total_minutes % 60;
  hours += total_minutes / 60;
}

void Time::AddHr(int h)
{
  hours += h;
}

void Time::Reset(int h, int m)
{
  hours = h;
  minutes = m;
}

Time Time::Sum(const Time& t) const
{
  Time tmp;
  int total_minutes = t.minutes + minutes;
  tmp.minutes = total_minutes % 60;
  tmp.hours += hours + t.hours + total_minutes / 60;
  return tmp;
}

void Time::Show() const
{
  std::cout  <<  hours << " hours "  << minutes << " minutes" << std::endl;

}

我们再写一个简单的测试程序:

//usetime0.cpp

#include <iostream>
#include "mytime0.hpp"

int main()
{
  using std::cout;
  using std::endl;
  
  Time time_work;
  Time time_work_morning(2, 35);
  Time time_work_afternoon(4, 40);

  cout << "morning work time: ";
  time_work_morning.Show();
  cout << endl;
  
  cout << "afternoon work time: ";
  time_work_afternoon.Show();
  cout << endl;
    
  time_work = time_work_morning.Sum(time_work_afternoon);   
   
  cout << "total time: ";
  time_work.Show();
  cout << endl;
  
  return 0;
}

运行结果如下:

morning work time: 2 hours 35 minutes

afternoon work time: 4 hours 40 minutes

total time: 7 hours 15 minutes

可以看到,我们要计算两个Time类对象的和,需要这样调用:

time_work = time_work_morning.Sum(time_work_afternoon);   

实际上,我们可以直接重载加法运算符,只要将Sum()的名称改为operator+即可。
修改后的类声明如下:

//mytime1.hpp
#ifndef _MYTIME0_HPP_
#define _MYTIME0_HPP_
class Time
{
private:
  int hours;
  int minutes;
public:
  Time();
  Time(int h, int m = 0);
  void AddMin(int m);
  void AddHr(int h);
  void Reset(int h = 0, int m = 0);
  Time operator+(const Time& t) const;              //此成员函数返回一个Time类对象,因为加法的结果需要一个新的变量来接收,比如 a = b + c;
  void Show() const;
};
#endif

修改后的类方法实现如下:

//mytime1.cpp
#include <iostream>
#include "mytime1.hpp"

Time::Time()
{
  hours = minutes = 0;
}

Time::Time(int h, int m)
{
  hours = h;
  minutes = m;
}

void Time::AddMin(int m)
{
  int total_minutes  = minutes + m;
  minutes = total_minutes % 60;
  hours += total_minutes / 60;
}

void Time::AddHr(int h)
{
  hours += h;
}

void Time::Reset(int h, int m)
{
  hours = h;
  minutes = m;
}

Time Time::operator+(const Time& t) const
{
  Time tmp;
  int total_minutes = t.minutes + minutes;
  tmp.minutes = total_minutes % 60;
  tmp.hours += hours + t.hours + total_minutes / 60;
  return tmp;
}

void Time::Show() const
{
  std::cout  <<  hours << " hours "  << minutes << " minutes" << std::endl;

}

将Sum替换成operator+之后,我们既可以使用如下的方式来调用:

time_work = time_work_morning.operator+(time_work_afternoon);   

也可以使用如下的方法使用:

time_work = time_work_morning + time_work_afternoon;   

需要注意,在运算符表示法中,运算符左侧的对象是调用对象,运算符右边的对象是作为参数被传递的对象。

我们使用下这个新的类:

//usetime1.cpp

#include <iostream>
#include "mytime1.hpp"

int main()
{
  using std::cout;
  using std::endl;
  
  Time time_work;
  Time time_work_morning(2, 35);
  Time time_work_afternoon(4, 40);

  cout << "morning work time: ";
  time_work_morning.Show();
  cout << endl;
  
  cout << "afternoon work time: ";
  time_work_afternoon.Show();
  cout << endl;
    
  time_work = time_work_morning + time_work_afternoon;   
   
  cout << "total time: ";
  time_work.Show();
  cout << endl;
  
  Time time_work_evening(2, 30);
  cout << "evening work time: ";
  time_work_evening.Show();
  cout << endl;

  time_work = time_work_evening.operator+(time_work);
  cout << "total time: ";
  time_work.Show();
  cout << endl;
  
  time_work = time_work_morning + time_work_afternoon+ time_work_evening;
  cout << "total time: ";
  time_work.Show();
  cout << endl;
  return 0;
}

运行结果如下:

morning work time: 2 hours 35 minutes

afternoon work time: 4 hours 40 minutes

total time: 7 hours 15 minutes

evening work time: 2 hours 30 minutes

total time: 9 hours 45 minutes

total time: 9 hours 45 minutes

我们在使用时,使用了这样的语句:

time_work = time_work_morning + time_work_afternoon + time_work_evening;

为什么可以这么做呢?那是因为+是从左向右的运算符,因此上述的语句会首先被转换成这样:

time_work = time_work_morning.operator+(time_work_afternoon + time_work_evening);

然后接着转换成这样:

time_work = time_work_morning.operator+(time_work_afternoon.operator+(time_work_evening));

time_work_afternoon.operator+(time_work_evening) 返回了一个Time对象,此对象是两者之和,然后该对象称为函数调用 time_work_morning.operator+()的参数,该调用返回time_work_morning与表示time_work_afternoon和time_work_evening之和的time对象的和。总之,最后的返回值是time_work_morning、time_work_afternoon和time_work_evening的和。

posted @ 2024-03-29 23:39  superbmc  阅读(3)  评论(0编辑  收藏  举报