【问题标题】:Operator overloading logic issues运算符重载逻辑问题
【发布时间】:2019-04-16 09:58:13
【问题描述】:

我们在课堂上的一项任务是创建一个程序,该程序使用对象来显示小时、分钟和秒。有了这些数字,我们现在必须重载各种运算符,将秒/分钟增加 1,并使用 ++ 和 -- 减少它们。我在使用 -- 运算符时遇到了一些问题,因为它没有按预期工作,如果我输入 0 分钟,它会减少返回值的分钟数,例如 128 分钟。当我开始做这件事时,我真的很感激一些帮助。

然后第二部分是使用其他运算符 (> =

Main.cpp

#include <iostream>
#include "Time.h"

using namespace std;

int main() {

    int hour1, minute1, second1, hour2, minute2, second2;

    cout << "Enter time A (hh, mm, ss): ";
    cin >> hour1;
    cin >> minute1;
    cin >> second1;
    cout <<endl;

    /*cout << "Enter time B(hh, mm, ss): ";
    cin >> hour2;
    cin >> minute2;
    cin >> second;
    cout <<endl;*/

   Time T1(hour1, minute1, second1);

   ++T1;                    //Increases seconds by 1
   T1.displayTime();

   T1++;                    //Increases minutes by 1
   T1.displayTime();

   --T1;                    //Decreases seconds by 1
   T1.displayTime();

   T1--;                    //Decreases minutes by 1
   T1.displayTime();


   return 0;
}

时间.h

#ifndef TIME_H
#define TIME_H

class Time
{
    public:
        Time();
        Time (int h, int m, int s);

        void displayTime();

        Time operator++();
        Time operator++(int);

        Time operator--();
        Time operator--(int);
        /*Time operator>();
        Time operator<();
        Time operator>=();
        Time operator<=();
        Time operator==();
        Time operator!=();*/

    private:
        int hours;
        int minutes;
        int seconds;
};

#endif // TIME_H

时间.cpp

#include <iostream>
#include "Time.h"

using namespace std;

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

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

void Time::displayTime(){
    cout << "Hours: " << hours <<" Minutes: " << minutes << " Seconds: " <<seconds <<endl;
}

Time Time::operator++(){ //Prefix plus seconds
    ++seconds;
    if (minutes >= 60){
        ++hours;
        minutes -= 60;
    }
    if (seconds >= 60){
        ++minutes;
        seconds -= 60;
    }
    return Time(hours, minutes, seconds);
}

Time Time::operator++(int){ //Postfix plus minutes
    Time T(hours, minutes, seconds);

    ++minutes;
    if(minutes >=60){
        ++hours;
        minutes -= 60;
    }
    if (seconds >= 60){
        ++minutes;
        seconds -= 60;
    }
    return T;
}

Time Time::operator--(){ //PREFIX MINUSS seconds
    --seconds;

    if (seconds == 0){
        --minutes;
        seconds += 59;
    }

    if (minutes == 0){
        --hours;
        minutes += 59;
    }

    return Time(hours, minutes, seconds);
}

Time Time::operator--(int){ //POSTFIX MINUSS minutes
    Time T(hours, minutes, seconds);
    --minutes;

    if (minutes == 0){
        --hours;
        minutes += 59;
    }
    if (seconds == 0){
        --minutes;
        seconds += 59;
    }
    return T;
}


/*Time Time::operator>(){

}

Time Time::operator<(){

}

Time Time::operator>=(){

}

Time Time::operator<=(){

}

Time Time::operator==(){

}

Time Time::operator!=(){

}
*/

如果您发现任何其他错误,请告诉我。

因此,分钟数没有正确减去。似乎它只是从 0 开始,但没有增加必要的秒数(如果有意义的话)。

谢谢。

【问题讨论】:

  • 请阅读minimal reproducible example 并删除代码中被注释掉的部分。这看起来像一堵巨大的代码墙,实际上并没有那么多
  • 正如@user463035818 所说,您的示例可能是完整的,但远非最小。
  • 你写了Time::Time(int h, int m, int s){ hours = h; minutes = m; seconds = s; } - 这更好(使用初始化列表):Time::Time(int h, int m, int s) : hours(h), minutes(m), seconds(s) { }
  • 检查秒数或分钟数是否超过60 的方式远非最佳。使用除法、模数和正确的排序(秒优先,然后是分钟等)。
  • 您应该先增加分钟数,然后再增加小时数。

标签: c++ oop operator-overloading overloading


【解决方案1】:

我在使用 -- 运算符时遇到了一些问题

其实你还有很多麻烦! operator++ 已经无法按预期工作。试试:

Time t(0, 59, 59);
++t;

一旦你用溢出增加秒数,下一个可能溢出的就是分钟,所以你需要先检查这些!

++seconds;
if(seconds == 60)
{
    seconds = 0;
    ++minutes;
    // only, if minutes were incremented, they can overflow, so check only here needed
   if(minutes == 60)
   {
       minutes = 0;
       // open: how do you want to handle hours overflowing?
       // variant 1: just go on, counting 23, 24, 25, ...
       ++hours;
       // variant 2: restart at 0:
       hours = (hours + 1) % 24;
       // variant 3 (my favourite): rember in a flag that we overflowed
       // (and have a getter for so that user can check):
       isWrapAround = hours == 23; // new member variable of type bool
       hours = (hours + 1) % 24;
   }
}

类似地,您将处理operator--,只需将每次出现的++ 替换为--,并将溢出检测调整为下溢检测。小心后者:您的原始代码没有进行正确的下溢检测:

--seconds;
if(seconds == 0)

当我们实际上还剩 1 秒时,这已经减少了分钟,但 00:00:00 是有效时间!因此,您需要检查 0 before 递减(if(seconds-- == 0) 或在之后检查负值(--seconds; if(seconds == -1)if (seconds &lt; 0))。通过此修复,+= 59 将不再正确或者,您需要+= 60,或者最好只需要= 59

通常,前置递增和递减运算符返回对当前对象的引用。这将允许 e。 G。 ++(++time):

Time& Time::operator++()
{
    // increment as described
    return *this;
}

后递增和递减运算符非常奇怪......请重新验证它是否真的是减少/减少分钟的任务(如果是这样,我只能摇头你的老师...)。这对任何人来说都是一个惊喜,因为操作员的行为与通常的行为完全不同!后者是:

Time operator++(int)
{
    Time tmp(*this);
    ++*this;
    return tmp;
}

如果你真的,真的应该增加分钟数(注意讽刺的是:post-X-crement 操作符实际上表现得像 pre-X-crement,至少就像你最初的方法一样):离开秒不动。然后,您在后运算符中需要的只是 body 的最外层 if 在相应的预变体中。然后可以将这些重写(以避免代码重复)为:

++seconds;
if(seconds == 60)
{
    seconds = 0;
    *this++; // use post-fix to adjust minutes...
}

最后:比较:不幸的是,我们还没有可用的 C++20,否则我们可以简单地实现宇宙飞船运算符 (&lt;=&gt;)... 没关系,我们仍然可以使用普通函数代替在运算符中使用这个:

int Time::compare(Time const& other) const
{
    // most relevant are hours, if these differ, values of minutes or
    // seconds don't matter any more...
    int result = hours - other.hours;
    if(result == 0)
    {
        // so hours are the same...
        // minutes then are relevant next
        result = minutes - other.minutes;
        if(result == 0)
            result = seconds - other.seconds;
    }
    return result;
}

那么所有要实现的操作符如下:

bool Time::operator@(Time const& other) const
{
    return compare(other) @ 0;
}

其中@ 代表您需要的所有运算符(==!=&lt;&lt;=&gt;&gt;=)。


奖励:无需单独标记即可记住溢出:

您不再需要另一个变量,但它需要更复杂的逻辑。

一开始,留下 -1 (operator--) 表示发生了回绕。相应地,环绕的吸气剂将是return hours == -1;

在我们之前直接使用hours任何其他地方,我们现在将使用getter for,如下所示:

int Time::getHours() const
{
    return hours + (hours == -1);
}

计算增量值稍微复杂一些:

hours = (getHours() + 1) % 24 - (hours == 23);

【讨论】:

  • 这真的很有帮助。我认为我的 ++ 和 -- 现在可以工作,运行了几次,一切看起来都很好。现在进行比较,有点挣扎,但我会到达那里。谢谢!
  • @Acancogua 在比较 (>) 中 main.cpp 中会是什么样子? Time T2 (hour2, minute2, second2); //Creating the second object T1&gt;T2; 或者我离这儿很远?
  • @B.Baxter 确切地说:Time t1(h1, m1, s1), t2(h2, m2, s2); if(t2 &gt; t1)...;;如果使用指针,则需要取消引用(否则会比较指针地址):Time* t1 = ...; Time* t2 = ...; if(*t2 &gt; *t1)....
  • 实际上,您也可以将单个对象与其自身进行比较:Time t1(h, m, s); if(t1 &lt; t1) – 如果操作符按照通常的含义正确实现,则无论初始化哪个值,它都应该始终产生一个常量值,仅取决于使用的运算符类型。唯一的例外:如果涉及浮点比较并且值为NaN,因为NaN(更准确地说:几种表示中的任何一种)比较不等于anything,甚至它本身...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 2013-11-01
  • 1970-01-01
  • 2023-02-16
  • 1970-01-01
相关资源
最近更新 更多