当我只重载它以接受Rational类型的参数时,我的Rational Number类如何使用+ =和long long参数?

时间:2017-03-03 13:44:11

标签: c++ operator-overloading

我已经在我的实现文件中实现了operator+=(Rational),但我意外地注意到Rational+= long long有效,即使我没有实现该特定功能。

我的主要功能是我使用plusequals += num时的相关功能。

plusequals声明为Rational plusequals,num声明为long long num。两者都被初始化为包含来自用户输入的值。

是什么给出的?在我看来,这应该不起作用,但确实如此。

这是我的头文件:

#ifndef _RATIONAL_H_
#define _RATIONAL_H_

#include<iostream>


using namespace std;

class Rational
{
long long _p;
long long _q;

void simplify();

public:
Rational();
Rational (long long p, long long Q = 1);
Rational (const Rational&);

Rational& operator= (const Rational&);
Rational& operator+= (const Rational&);
Rational& operator-= (const Rational&);
Rational& operator*= (const Rational&);
Rational& operator/= (const Rational&);

friend ostream& operator<< (ostream&, const Rational&);
friend istream& operator>> (istream&, Rational&);

Rational operator+ (const Rational&);
Rational operator+ (long long) const;
friend Rational operator+ (long long, const Rational&);
Rational operator- (const Rational&);
Rational operator- (long long) const;
friend Rational operator- (long long, const Rational&);
Rational operator* (const Rational&);
Rational operator* (long long) const;
friend Rational operator* (long long, const Rational&);
Rational operator/ (const Rational&);
Rational operator/ (long long) const;
friend Rational operator/ (long long, const Rational&);

bool operator== (const Rational&) const;
bool operator== (long long) const;
friend bool operator== (long long, const Rational&);
bool operator!= (const Rational&) const;
bool operator!= (long long) const;
friend bool operator!= (long long, const Rational&);
bool operator> (const Rational&) const;
bool operator> (long long) const;
friend bool operator> (long long, const Rational&);
bool operator< (const Rational&) const;
bool operator< (long long) const;
friend bool operator< (long long, const Rational&);
bool operator>= (const Rational&) const;
bool operator>= (long long) const;
friend bool operator>= (long long, const Rational&);
bool operator<= (const Rational&) const;
bool operator<= (long long) const;
friend bool operator<= (long long, const Rational&);

Rational operator++ (int);
Rational operator-- (int);
Rational& operator++ ();
Rational& operator-- ();
Rational operator- () const;
Rational operator+ () const;

Rational pow (unsigned exp) const;
Rational inverse() const;
};

#endif

以下是实施:

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

void validate (long long, long long);

int gcd (long long, long long);

Rational::Rational()
{
    _p = 0;
    _q = 1;
}

Rational::Rational (long long p, long long Q)
{
    validate (p, Q);
    _p = p;
    _q = Q;
}

Rational::Rational (const Rational& rat)
{
    this->_p = rat._p;
    this->_q = rat._q;
}
void Rational::simplify()
{
    // Fixes negative denominators.
    if (_q < 0)
    {
        _p *= -1;
        _q *= -1;
    }

    // Simplifies Rational Numbers.
    int denom = gcd(_p, _q);
    _p /= denom;
    _q /= denom;

}

Rational& Rational::operator= (const Rational& rat)
{
    _p = rat._p;
    _q = rat._q;

    return *this;
}

Rational& Rational::operator+= (const Rational& rat)
{
    _p = ((_p * rat._q) + (_q * rat._p));
    _q *= rat._q;

    this->simplify();

    return *this;
}

Rational& Rational::operator-= (const Rational& rat)
{
    _p = ((_p * rat._q) - (_q * rat._p));
    _q *= rat._q;

    this->simplify();

    return *this;
}

Rational& Rational::operator*= (const Rational& rat)
{
    _p *= rat._p;
    _q *= rat._q;

    this->simplify();

    return *this;
}

Rational& Rational::operator/= (const Rational& rat)
{
    if (rat._p == 0)
    {
        throw "Division by zero not allowed";
    }
    _p *= rat._q;
    _q *= rat._p;

    this->simplify();

    return *this;
}

ostream& operator<< (ostream& os, const Rational& rat)
{
    os << rat._p << ":" << rat._q;

    return os;
}

istream& operator>> (istream& is, Rational& rat)
{
    long long p, q;

    is >> p >> q;
    validate(p, q);
    rat._p = p;
    rat._q = q;
    rat.simplify();

    return is;
}

Rational Rational::operator+ (const Rational& rat)
{
    Rational result(*this);

    result += rat;
    result.simplify();

    return result;
}

Rational Rational::operator+ (long long num) const
{
    Rational result(*this);
    Rational temp(num);

    result += temp;
    result.simplify();

    return result;
}

Rational operator+ (long long num, const Rational& rat)
{
    Rational result(num);
    result += rat;
    result.simplify();

    return result;
}

Rational Rational::operator- (const Rational& rat)
{
    Rational result(*this);

    result -= rat;
    result.simplify();

    return result;
}

Rational Rational::operator- (long long num) const
{
    Rational result(*this);
    Rational temp(num);

    result -= temp;
    result.simplify();

    return result;
}

Rational operator- (long long num, const Rational& rat)
{
    Rational result(num);
    result -= rat;
    result.simplify();

    return result;
}

Rational Rational::operator* (const Rational& rat)
{
    Rational result(*this);

    result *= rat;
    result.simplify();

    return result;
}

Rational Rational::operator* (long long num) const
{
    Rational result(*this);
    Rational temp(num);
    result *= temp;
    result.simplify();

    return result;
}

Rational operator* (long long num, const Rational& rat)
{
    Rational result(num);
    result *= rat;
    result.simplify();

    return result;
}

Rational Rational::operator/ (const Rational& rat)
{
    Rational result(*this);

    result /= rat;
    result.simplify();

    return result;
}

Rational Rational::operator/ (long long num) const
{
    Rational result(*this);
    Rational temp(num);

    result /= temp;
    result.simplify();

    return result;
}

Rational operator/ (long long num, const Rational& rat)
{
    Rational result(num);
    result /= rat;
    result.simplify();

    return result;
}

bool Rational::operator== (const Rational& rat) const
{
    bool result;

    if ((this->_p == rat._p) && (this->_q == rat._q))
    {
        result = true;
    }
    else
    {
        result = false;
    }

    return result;
}

bool Rational::operator== (long long num) const
{
    bool result;
    Rational temp(num);

    result = (*this == temp);

    return result;
}

bool operator== (long long num, const Rational& rat)
{
    bool result;

    result = (rat == num);

    return result;
}

bool Rational::operator!= (const Rational& rat) const
{
    return !(*this == rat);
}

bool Rational::operator!= (long long num) const
{
    return !(*this == num);
}

bool operator!= (long long num, const Rational& rat)
{
    return !(num == rat);
}

bool Rational::operator> (const Rational& rat) const
{
    bool result;

    if ((this->_p / this->_q) > (rat._p / rat._q))
    {
        result = true;
    }
    else
    {
        result = false;
    }

    return result;
}

bool Rational::operator> (long long num) const
{
    bool result;
    Rational temp(num);

    result = (*this > temp);

    return result;
}

bool operator> (long long num, const Rational& rat)
{
    bool result;

    result = (rat < num);

    return result;
}

bool Rational::operator< (const Rational& rat) const
{
    bool result;

    if (!(*this > rat) && !(*this == rat))
    {
        result = true;
    }
    else
    {
        result = false;
    }

    return result;
}

bool Rational::operator< (long long num) const
{
    bool result;
    Rational temp(num);

    result = (*this < temp);

    return result;
}

bool operator< (long long num, const Rational& rat)
{
    bool result;

    result = (rat > num);

    return result;
}

bool Rational::operator>= (const Rational& rat) const
{
    bool result;

    if (!(*this < rat))
    {
        result = true;
    }
    else
    {
        result = false;
    }

    return result;
}

bool Rational::operator>= (long long num) const
{
    bool result;
    Rational temp(num);

    result = (*this >= temp);

    return result;
}

bool operator>= (long long num, const Rational& rat)
{
    bool result;

    result = (rat <= num);

    return result;
}

bool Rational::operator<= (const Rational& rat) const
{
    bool result;

    if (!(*this > rat))
    {
        result = true;
    }
    else
    {
        result = false;
    }

    return result;
}

bool Rational::operator<= (long long num) const
{
    bool result;
    Rational temp(num);

    result = (*this <= temp);

    return result;
}

bool operator<= (long long num, const Rational& rat)
{
    bool result;

    result = (rat >= num);

    return result;
}

Rational Rational::operator++ (int) // Postfix
{
    Rational temp(*this);

    this->_p++;
    this->_q++;

    return temp;
}

Rational Rational::operator-- (int) // Postfix
{
    Rational temp(*this);

    this->_p--;
    this->_q--;

    return temp;
}

Rational& Rational::operator++()
{
    this->_p++;
    this->_q++;

    return *this;
}

Rational& Rational::operator--()
{
    this->_p--;
    this->_q--;

    return *this;
}

Rational Rational::operator-() const
{
    Rational temp(-(this->_p), (this->_q));

    return temp;
}

Rational Rational::operator+() const
{
    Rational temp(+(this->_p), +(this->_q));

    return temp;
}

Rational Rational::pow (unsigned exp) const
{
    Rational result(*this);
    Rational temp(*this);

    if (exp == 0)
    {
        result = 1;
    }
    else
    {
        for (unsigned i = 1; i < exp; i++)
        {
            result *= temp;
        }
    }

    return result;
}

Rational Rational::inverse() const
{
    Rational temp(this->_q, this->_p);

    return temp;
}

void validate(long long p, long long q)
{
    p++; // Supress error for unused value. Decided to keep value in parameter list to maintain clarity.
    if (q == 0)
    {
        throw "Zero Denominator";
    }
}

int gcd(long long p, long long q)
{
    // Euclid's Algorithm
    if (q == 0)
    {
        return p;
    }
    return gcd (q, p%q);
}

好的方面,我正在使用的测试main()

#include <string>
#include <iostream>
#include "Rational.h"

int main()
{
    while (true)
    {
        Rational rat1;
        Rational rat2;
        Rational rat3;
        long long num;
        unsigned exp;
        Rational power(rat1);
        string hello = "hello";

        // Get input
        try
        {
            cout << "Please enter a numerator and denominator separated by a space: ";
            cin >> rat1;
            cout << endl;
            cout << "Please enter a second numerator and denomintator seperated by a space: ";
            cin >> rat2;
            cout << endl;
            cout << "Please enter a numerator and denominator separated by a space for a third Rational number: ";
            cin >> rat3;
            cout << endl;
            cout << "Enter a number to use for arithmetic operations: ";
            cin >> num;
            cout << endl;
            cout << "Please enter a positive integer to use an exponent :";
            cin >> exp;
            cout << endl;
        }
        catch (char const* err)
        {
            cerr << err << " - Non-Zero denominators only ya big goon.\n";
        }

        cout << endl;

        cout << "You put: " << rat1 << " and: " << rat2 << endl;

        Rational plusequals (rat1);
        Rational minusequals (rat1);
        Rational timesequals (rat1);
        Rational divequals (rat1);

        plusequals += rat2;
        minusequals -= rat2;
        timesequals *= rat2;
        try
        {
            divequals /= rat2;
        }
        catch (const char* msg)
        {
            cerr << msg << endl;
        }

        cout << "+= : " << plusequals << "\n-= : " << minusequals << "\n*= : " << timesequals << "\n/= : " << divequals << endl;

        plusequals = rat1;
        minusequals = rat1;
        timesequals = rat1;
        divequals = rat1;

        plusequals += num;
        minusequals -= num;
        timesequals *= num;
        try
        {
            divequals /= num;
        }
        catch (const char* msg)
        {
            cerr << msg << endl;
        }

        cout << "\nRational = " << rat1<< ", num = " << num << "  :\n";
        cout << rat1 << " += " << num << ": " << plusequals << endl << rat1 << " -= " << num << ": " << minusequals << endl << rat1 <<" *= " << num << ": " << timesequals << endl << rat1 << " /= " << num << ": " << divequals << endl;

        plusequals = rat1;
        minusequals = rat1;
        timesequals = rat1;
        divequals = rat1;

        plusequals += rat3;
        minusequals -= rat3;
        timesequals *= rat3;
        try
        {
            divequals /= rat3;
        }
        catch (const char* msg)
        {
            cerr << msg << endl;
        }

        cout << "\nRational = " << rat1<< ", Rational = " << rat3 << "  :\n";
        cout << rat1 << " += " << rat3 << ": " << plusequals << endl << rat1 << " -= " << rat3 << ": " << minusequals << endl << rat1 << " *= " << rat3 << ": " << timesequals << endl << rat1 << " /= " << rat3 << ": " << divequals << endl;


        power = rat1.pow(exp);
        cout << endl << rat1 << " raised to the power of " << exp << " : ";
        cout << power << endl;

        cout << "The multiplicative inverse of " << rat1 << " is " << rat1.inverse() << endl;

        // Comparison
        cout << endl << endl;
        if (rat1 == rat2)
        {
            cout << rat1 << " = " << rat2 << endl;
        }
        if (rat1 != rat2)
        {
            cout << rat1 << " != " << rat2 << endl;
        }
        if (rat1 <= rat2)
        {
            cout << rat1 << " <= " << rat2 << endl;
        }
        if (rat1 >= rat2)
        {
            cout << rat1 << " >= " << rat2 << endl;
        }
        if (rat1 < rat2)
        {
            cout << rat1 << " < " << rat2 << endl;
        }
        if (rat1 > rat2)
        {
            cout << rat1 << " > " << rat2 << endl;
        }
    }
}

此外,我应该注意,我知道我的头文件中不应该using namespace std; ...但是我们需要直接从我们的教授那里复制标题。他还坚持认为我们使用的是我在这个特定项目中使用的支架样式,我觉得它很难看,但它就是它的本质。他非常特别。不过,对这项任务的任何其他改进/见解都将非常感激。

3 个答案:

答案 0 :(得分:1)

Rational_object += (long long)_object

有效,因为您有converting constructor

Rational (long long p, long long Q = 1);

这使得编译器可以隐式地将long long转换为Rational。您可以通过标记此类构造函数explicit

来阻止此行为

答案 1 :(得分:1)

long long隐式转换为Rational,因为您的类具有Rational (long long p, long long Q = 1);构造函数。您可以使用explicit keyword来避免隐式转换。

答案 2 :(得分:1)

回答关于+=的问题:看看这个构造函数:

Rational (long long p, long long Q = 1);

构造函数未使用explicit关键字进行修饰,这意味着它可用于隐式转换。

如果+=表达式的操作数类型为Rationallong long,则会发生什么情况,编译器会搜索operator +=的所有定义,然后查看是否存在它们可以接受操作数类型(即重载决策)。

如果没有直接匹配(在您的情况下不匹配),它将尝试查看是否有任何隐式转换可以使它们匹配。您的+=双方都需要Rational。左侧操作已经是Rational,那里不需要任何操作。右侧是long long,但存在从long longRational的隐式转换(通过构造函数)。因此,编译器发出代码以从Rational创建临时long long,然后将此临时Rational提供给您的operator +=

您可以通过将构造函数标记为explicit来阻止这些隐式转换,但我认为您这样做是错误的。毕竟,写“1/2 + 1 = 3/2”有什么问题吗?我们不需要写“1/2 + 1/1”。

数字之间的隐式转换非常有用。由于从3.14 + 1int的隐式转换,double是完全有效的C ++(并且非常合理)。

关于您的其他请求,

  

尽管如此,我们非常感谢对作业的任何其他改进/见解。

这不是Stack Overflow的主题。假设您的代码有效,您可能会对Code Review获得有趣的反馈。