【问题标题】:increment and decrement operator overloading递增和递减运算符重载
【发布时间】:2015-08-22 21:34:44
【问题描述】:

这是我一直试图解决的问题:

定义一个名为 PrimeNumber 的类来存储一个素数。默认构造函数应将质数设置为 1。添加另一个构造函数,允许调用者设置质数。另外,添加一个函数来获取素数。最后,重载前缀和后缀 ++-- operators,以便它们返回一个 PrimeNumber 对象,该对象是下一个最大的素数(对于 ++)和下一个最小的素数(对于 --)。例如,如果对象的质数设置为 13,则调用 ++ 应返回质数设置为 17 的 PrimeNumber 对象。为该类创建适当的测试程序。

#include <iostream>
#include <cstdlib>
using namespace std;

class PrimeNumber
{
public:
    PrimeNumber() : pNum(1) {}
    PrimeNumber(int setNum) : pNum(setNum) {}
    int getNum() const { return pNum; }
    PrimeNumber operator ++(); //prefix
    PrimeNumber operator ++(int ignoreMe); //postfix
    PrimeNumber operator --();
    PrimeNumber operator --(int ignoreMe);
    bool isPrime(const int& num);
private:
    int pNum;
};

int main( )
{
    int x;
    cout << "enter prime number => ";
    cin >> x;

    PrimeNumber p(x);
    PrimeNumber hold = p++;
    cout << "Value of hold => " << hold.getNum() << endl;
    cout << "Value of p => " << p.getNum() << endl;

    cout << "enter prime number => ";
    cin >> x;

    PrimeNumber p2(x);
    PrimeNumber hold2 = ++p2;
    cout << "Value of hold2 => " << hold2.getNum() << endl;
    cout << "Value of p2 => " << p2.getNum() << endl;

    cout << "enter prime number => ";
    cin >> x;

    PrimeNumber p3(x);
    PrimeNumber hold3 = p3--;
    cout << "Value of hold3 => " << hold3.getNum() << endl;
    cout << "Value of p3 => " << p3.getNum() << endl;

    cout << "enter prime number => ";
    cin >> x;

    PrimeNumber p4(x);
    PrimeNumber hold4 = --p4;
    cout << "Value of hold4 => " << hold4.getNum() << endl;
    cout << "Value of p4 => " << p4.getNum() << endl;


    return 0;
}
bool PrimeNumber::isPrime(const int& num)
{
    if (num < 2)
    {
        return false;
    }
    else if (num == 2)
    {
        return true;
    }
    else
    {
        for (int i = 2; i <= num / 2; i++)
        {
            if (num % i == 0)
            {
                return false;
            }
        }
    }
    return true;
}

PrimeNumber PrimeNumber::operator ++() //prefix
{
    pNum += 1;
    while (!isPrime(pNum))
    {
        pNum++;
    }
    return pNum;
}
PrimeNumber PrimeNumber::operator ++(int ignoreMe) //postfix
{
    int temp = pNum += 1;
    while (!isPrime(pNum))
    {
        temp = pNum;
        pNum++;
    }
    return temp;
}
PrimeNumber PrimeNumber::operator --() //prefix
{
    pNum -= 1;
    while (!isPrime(pNum))
    {
        pNum--;
    }
    return pNum;
}
PrimeNumber PrimeNumber::operator --(int ignoreMe) //postfix
{
    int temp = pNum -= 1;
    while (!isPrime(pNum))
    {
        temp = pNum;
        pNum--;
    }
    return temp;
}

该问题与减量运算符重载有关。我认为增量运算符按预期工作。如果没有,请指出。但是,hold 值对于后缀递增和递减操作似乎并不像预期的那样。如何解决问题。另外,如有其他可纠正的错误,请指出。

Output                              Expected Output
----------                          -------------------
enter prime number => 11            enter prime number => 11
Value of hold => 12                 Value of hold => 11
Value of p => 13                    Value of p => 13
enter prime number => 11            enter prime number => 11
Value of hold2 => 13                Value of hold2 => 13
Value of p2 => 13                   Value of p2 => 13
enter prime number => 11            enter prime number => 11
Value of hold3 => 8                 Value of hold3 => 11
Value of p3 => 7                    Value of p3 => 7
enter prime number => 11            enter prime number => 11
Value of hold4 => 7                 Value of hold4 => 7
Value of p4 => 7                    Value of p4 => 7

【问题讨论】:

  • 请注意,看起来两个后缀运算符都没有返回正确的结果。
  • 你能举个例子吗?不,我没有测试,但逻辑看起来不对。
  • 你的后缀运算符都错了。它们应该返回对象的旧值,而不是新值加或减一。
  • 我刚刚意识到@n.m。怎么解决?
  • 如何修复后缀hold 问题?我已经编辑了我的问题@Wimmel

标签: c++ operator-overloading


【解决方案1】:
PrimeNumber PrimeNumber::operator --(int ignoreMe) //postfix
{
    int temp = pNum -= 1;
    while (!isPrime(pNum))
    {
        temp = pNum;
        temp--;
    }
    return temp;
}

这段代码将永远运行,因为 pNum 在循环内没有改变。您的程序在最后一次输入后挂起,试图执行后缀operator--

编辑

你的后缀运算符:

PrimeNumber PrimeNumber::operator --(int ignoreMe) //postfix
{
    int temp = pNum -= 1;
    while (!isPrime(pNum))
    {
        temp = pNum;
        pNum--;
    }
    return temp;
}

仍然无效。这是正确的版本恕我直言:

PrimeNumber PrimeNumber::operator --(int ignoreMe) //postfix
{
    int temp = pNum;
    while (!isPrime(--pNum)) {}
    return temp;
}

oprator++(int) 也一样:

PrimeNumber PrimeNumber::operator ++(int ignoreMe) //postfix
{
    int temp = pNum;
    while (!isPrime(++pNum)) {}
    return temp;
}

【讨论】:

    【解决方案2】:

    所以您的代码存在一些基本问题。

    • 一般来说,我们希望前缀运算符返回对自身的引用。
    • 您的返回值通常会调用不必要的隐式 PrimeNumber 构造函数。

    这是您可以遵循的基本规则:

    • 前缀样式:酌情执行递增或递减,然后返回*this

    • 后缀样式:通过auto copy = *this创建自己的副本,然后调用相应的前缀运算符。

    让我们尝试实现这个:

    PrimeNumber & PrimeNumber::operator ++() //prefix
    {
        pNum += 1;
        while (!isPrime(pNum))
            pNum++;
        return *this;
    }
    
    PrimeNumber PrimeNumber::operator ++(int ignoreMe) //postfix
    {
        auto copy = *this;
        ++(*this);
        return copy;
    }
    
    PrimeNumber & PrimeNumber::operator --() //prefix
    {
        pNum -= 1;
        while (!isPrime(pNum))
            pNum--;
        return *this;
    }
    
    PrimeNumber PrimeNumber::operator --(int ignoreMe) //postfix
    {
        auto copy = *this;
        --(*this);
        return copy;
    }
    

    此外,测试代码在给出错误结果时应该抛出断言等。我不需要考虑测试是对还是错。

    int main( ) {
        auto x = PrimeNumber(17);
        auto hold = x++;
        assert(hold.getNum() == 17);
        assert(x.getNum() == 19);
    
        x = PrimeNumber(18);
        hold = x--;
        assert(hold.getNum() == 18);
        assert(x.getNum() == 17);
    
        x = PrimeNumber(25);
        hold = ++x;
        assert(hold.getNum() == 29);
        assert(x.getNum() == 29);
    
        x = PrimeNumber(19);
        hold = --x;
        assert(hold.getNum() == 17);
        assert(x.getNum() == 17);
    
        cout << "Success!\n"
    }
    

    这个main() 只会在所有断言都为真时打印Success!

    【讨论】:

    • 老手我知道使用前缀参考,但我在 C++ 书中读过 we find it opens the door to too many problems to return by reference with increment or decrement operators, and so we always simply return by value for all versions of the increment and decrement operators.。我不使用参考。你觉得这个主意怎么样?我应该使用引用方式来为递增和递减操作添加前缀吗?此外,使用auto 有什么好处,你为什么使用它?你介意教书吗?
    • 我使用auto 是因为它比PrimeNumber 短,而且更容易输入。
    • 关于你的书(或引用来自哪里)谈论不通过引用返回,我强烈不同意。我不知道他们担心什么问题,但我相信用户会期望operator++() 返回他们可以分配的引用。我当然会。
    • 一点我不明白后缀如何知道素数?
    • 后缀运算符在调用PrimeNumber::operator++(),即复制对象,然后调用前缀运算符。
    猜你喜欢
    • 2011-02-16
    • 2015-10-03
    • 2014-03-21
    • 1970-01-01
    • 2010-12-01
    • 2013-06-18
    • 2015-02-16
    • 2011-08-29
    相关资源
    最近更新 更多