11.2 计算时间:一个运算符重载示例

题目

今天早上在Priggs的账户上花费2小时35分钟,下午又花费了2小时40分钟,则总共花了多少时间。

mytime0.h

#ifndef MYTIME0_H
#define MYTIME0_H

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; //总时间
    void Show() const; //显示时间
};

#endif // MYTIME0_H

Time类提供用于调整和重新设置时间、显示时间、将两个时间相加的方法。

注意:当总的分钟数超过59时,AddMin()和Sum()方法是如何使用整数除法和求模运算符来调整minutes和hours值的。

mytime0.cpp

#include <iostream>
#include "mytime0.h"
using namespace std;

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

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

void Time::AddMin(int m)
{
    minutes += m;
    hours += minutes / 60;
    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 sum;
    sum.minutes = minutes + t.minutes;
    sum.hours = hours + t.hours + sum.minutes / 60;
    sum.minutes %= 60;
    return sum;
}

void Time::Show() const
{
    cout << hours << " hours, " << minutes << " minutes";
}

Sum()函数:参数是引用,返回类型不是引用。将参数声明为引用的目的是为了提高效率。如果按值传递Time对象,代码的功能将相同,但传递引用,速度将更快,使用的内存将更少。

然而,返回值不能是引用。因为函数将创建一个新的Time对象(sum),来表示另外两个Time对象的和。返回对象(如代码所做的那样)将创建对象的副本,而调用函数可以使用它。

然而,如果返回类型为Time&,则引用的将是sum对象。但由于sum对象是局部变量,在函数结束时将被删除,因此引用将指向一个不存在的对象。

使用返回类型Time意味着程序将在删除sum之前构造它的拷贝,调用函数将得到该拷贝。

警告:不要返回指向局部变量或临时对象的引用。函数执行完毕后,局部变量和临时对象将消失,引用将指向不存在的数据。

main.cpp

#include <iostream>
#include "mytime0.h"
using namespace std;

int main()
{
    Time planning;
    Time coding(2, 40);
    Time fixing(5, 55);
    Time total;
    cout << "planning time = ";
    planning.Show();
    cout << endl;

    cout << "coding tiem = ";
    coding.Show();
    cout << endl;

    cout << "fixing time = ";
    fixing.Show();
    cout << endl;

    total = coding.Sum(fixing);
    cout << "coding.Sum(fixing) = ";
    total.Show();
    cout << endl;

    return 0;
}

在这里插入图片描述

添加加法运算符

将Sum()的名称改为operator+()即可。并将结果用作方法名即可。在这里,可以在标识符中使用字母、数字或下划线之外的其他字符。

mytime1.h

#ifndef MYTIME1_H
#define MYTIME1_H

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; //重载运算符+
    void Show() const; //显示时间
};

#endif // MYTIME1_H

mytime1.cpp

#include <iostream>
#include "mytime1.h"
using namespace std;

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

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

void Time::AddMin(int m)
{
    minutes += m;
    hours += minutes / 60;
    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 sum;
    sum.minutes = minutes + t.minutes;
    sum.hours = hours + t.hours + sum.minutes / 60;
    sum.minutes %= 60;
    return sum;
}

void Time::Show() const
{
    cout << hours << " hours, " << minutes << " minutes";
}

和Sum()一样,operator+()是由Time对象调用的,它将第二个Time对象作为参数,并返回一个Time对象。因此,可以像调用Sum()那样来调用operator+()方法:

total =  coding.operator+(fixing); //函数符号

但将该方法命名为operator+()后,也可以使用运算符表示法:

total = coding + fixing; //运算符符号

两种表示法都将调用operator+()方法。

注意:在运算符表示法中,运算符左侧的对象(这里是coding)是调用对象,运算符右边的对象(这里是fixing)是作为参数被传递的对象。

main.cpp

#include <iostream>
#include "mytime1.h"
using namespace std;

int main()
{
    Time planning;
    Time coding(2, 40);
    Time fixing(5, 55);
    Time total;
    cout << "planning time = ";
    planning.Show();
    cout << endl;

    cout << "coding tiem = ";
    coding.Show();
    cout << endl;

    cout << "fixing time = ";
    fixing.Show();
    cout << endl;

    total = coding + fixing;
    cout << "coding + fixing = ";
    total.Show();
    cout << endl;

    Time morefixing(3, 28);
    cout << "more fixing time = ";
    morefixing.Show();
    cout << endl;
    total = morefixing.operator+(total);

    cout << "morefixing.operator+(total) = ";
    total.Show();
    cout << endl;

    return 0;
}

在这里插入图片描述
总之,operator+()函数的名称使得可以使用函数表示法或运算符表示调用它。

int a, b, c;
Time A, B, C;
c = a + b; //利用整型相加
C = A + B; //使用为 Time 对象定义的加法

可以将两个以上的对象相加吗?

t4 = t1 + t2 + t3; //合法的

由于+是从左向右结合的运算符。

t4 = t1.operator+(t2 + t3); //合法的

然后,函数参数本身被转换成一个函数调用。

t4 = t1.operator+(t2.operator+(t3)); //合法的

函数调用t2.operator+(t3)返回一个Time对象,后者是t2和t3的和。然而,该对象成为函数调用t1.operator+()的参数,该调用返回t1与表示t2和t3之和的Time对象的和。

重载限制

● 重载后的运算符必须至少有一个操作数是用户定义的类型,这将防止用户为标准类型重载运算符。因此,不能将减法符(-)重载为计算两个double值的和,而不是它们的差。
● 使用运算符时不能违反运算符原来的句法规则。例如,不能将求模运算符(%)重载成使用一个操作数:

int x;
Time shiva;
% x; //求模运算符无效
% shiva; //求模运算符重载无效

不能修改运算符的优先级。如果将加号运算符重载成将两个类相加,则新的运算符与原来的加号具有相同的优先级。
● 不能创建新运算符。例如,不能定义operator**()函数来求幂。
● 不能重载下面的运算符:
sizeof:sizeof运算符
.:成员运算符
.*:成员指针运算符
:::作用域解析运算符
?::条件运算符
typeid:一个RTTI运算符
const_cast:强制类型转换符运算符
dynamic_cast:强制类型转换运算符
reinterpret_cast:强制类型转换运算符
static_cast:强制类型转换运算符
● 通过成员或非成员函数进行重载,但下面的运算符只能通过成员函数进行重载。
=:赋值运算符
():函数调用运算符
[]:下标运算符
->:通过指针访问类成员的运算符

其他重载运算符

将两个时间相减或将时间乘以一个因子,这需要重载减法和乘法运算符。

Time operator-(const Time &t) const;
Time operator*(double n) const;

mytime2.h

#ifndef MYTIME2_H
#define MYTIME2_H

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 operator-(const Time &t) const; //重载减法
    Time operator*(double n) const; //重载乘法
    void Show() const;
};

#endif // MYTIME2_H

mytime2.cpp

#include <iostream>
#include "mytime2.h"
using namespace std;

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

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

void Time::AddMin(int m)
{
    minutes += m;
    hours += minutes / 60;
    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 sum;
    sum.minutes = minutes + t.minutes;
    sum.hours = hours + t.hours + sum.minutes / 60;
    sum.minutes %= 60;
    return sum;
}

Time Time::operator-(const Time &t) const
{
    Time diff;
    int tot1, tot2;
    tot1 = t.minutes + 60 * t.hours;
    tot2 = minutes + 60 * hours;
    diff.minutes = (tot2 - tot1) % 60;
    diff.hours = (tot2 - tot1) / 60;
    return diff;
}

Time Time::operator*(double mult) const
{
    Time result;
    long totalminutes = hours * mult * 60 + minutes * mult;
    result.hours = totalminutes / 60;
    result.minutes = totalminutes % 60;
    return result;
}



void Time::Show() const
{
    cout << hours << " hours, " << minutes << " minutes";
}

main.cpp

#include <iostream>
#include "mytime2.h"
using namespace std;

int main()
{
    Time planning;
    Time wedding(4, 35);
    Time waxing(2, 47);
    Time total;
    Time diff;
    Time adjusted;

    cout << "weeding time = ";
    wedding.Show();
    cout << endl;

    cout << "waxing tiem = ";
    waxing.Show();
    cout << endl;

    total = wedding + waxing;
    cout << "wedding + waxing = ";
    total.Show();
    cout << endl;

    diff = wedding - waxing;
    cout << "weeding time - waxing time = ";
    diff.Show();
    cout << endl;

    adjusted = total * 1.5;
    cout << "adjusted work time = ";
    adjusted.Show();
    cout << endl;

    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阳光开朗男孩

你的鼓励是我最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值