Operator Overloading: How to add and compare data

2019-09-19 09:31发布

问题:

I have two classes Integer and Fraction and one abstract class Number. I am suppose to perform addtion operation by overloading + and also I need to check equality of values using overloading of == operator on these classes.

Operations to be performed

1. Add Integer + Integer = Integer

2. Add Fraction + Fraction = Fraction

3. Add Integer + Fraction = Fraction

I have been able to do 1st and 2nd operation but not able to do addition of integer and fraction.

Below is the code snippet:

  1. Number.h

     #pragma once
    #include <iostream>
    template<class T>
    
    class Number
    {
        virtual const T operator+ (const T &) = 0;
        virtual void display(std::ostream &) const = 0;
        virtual bool operator==(const T& rhs) const = 0;
    
    };
    
  2. Integer.h

     #pragma once
     #include "Number.h"
     #include "Fraction.h"
    class Integer : public Number<Integer>
    {
        int intValue;
    
    public:
        void display(std::ostream &) const;
        int getValue() const;
        void setValue(int);
        Integer() {}
        Integer(int num);
        const Integer operator+ (const Integer &);
        virtual ~Integer() {}
        bool operator==(const Integer&) const;
    
    };
    
  3. Integer.cpp

    #include "Integer.h"
    #include "Number.h"
    #include <iostream>
    #include <string>
    
    // parameterized constructor
    Integer::Integer(int num)
    {
        intValue = num;
    }
    
    // return integer value
    
    int Integer::getValue() const
    {
        return this->intValue;
    }
    
    void Integer::setValue(int x)
    {
        this->intValue = x;
    }
    
    // operator "+" overloading
    const Integer Integer::operator+(const Integer &secondNumber)
    {
        Integer  temp = this->intValue + secondNumber.intValue;
        return temp;
    }
    
    // operator "=" overloading 
    void Integer::display(std::ostream& stream) const
    {
        stream << this->intValue;
    }
    
    // comparasion operator overload
    bool Integer::operator==(const Integer& rhs) const
    {
        return this->intValue == rhs.intValue;
    }
    
  4. Fraction.h

     #pragma once
     #include "Number.h"
     #include "Integer.h"
    
     class Fraction : public Number<Fraction>
     {
         Integer _numerator;
         Integer _denominator;
         public:
        void display(std::ostream &) const;
        Fraction() = delete;
        Fraction(const int &, const int &);
        const Fraction operator+ (const Fraction &);
        int gcdCalculate(int  val1, int  val2);
        int lcmCalculate(const int  val1, const int  val2);
        virtual ~Fraction() {}
        bool operator==(const Fraction& rhs) const;
     };
    
  5. Fraction.cpp

    #include "Fraction.h"
    #include <iostream>
    
    // parameterised constructor 
    Fraction::Fraction(const int & num, const int & den)
    {
        _numerator.setValue(num);
        _denominator.setValue(den);
    }
    
    // display the fraction value
    void Fraction::display(std::ostream & stream) const
    {
            if (this->_denominator == 0)
             std::cout << "Undefined: " << this->_numerator.getValue() << "/" << this->_denominator.getValue() << " (Divide By Zero Exception)";
    else
            stream << this->_numerator.getValue() << "/" << this->_denominator.getValue();
    }
    
    // "+" operator overloading
    const Fraction Fraction::operator+(const Fraction &numberTwo)
    {
        int lcm = lcmCalculate(this->_denominator.getValue(), numberTwo._denominator.getValue());
        int multiplier1 = 0;
        if (this->_denominator.getValue())
        multiplier1 = lcm / this->_denominator.getValue();
        int multiplier2 = 0;
        if (numberTwo._denominator.getValue())
            multiplier2 = lcm / numberTwo._denominator.getValue();
        return Fraction((this->_numerator.getValue() * multiplier1) + (numberTwo._numerator.getValue() * multiplier2), lcm);
    }
    
    
     // LCM Calculation
    
    int Fraction::lcmCalculate(const int  val1, const int  val2)
    {
        int temp = gcdCalculate(val1, val2);
        return temp ? (val1 / temp * val2) : 0;
    }
    
    // GCD Calculation
    int Fraction::gcdCalculate(int val1, int  val2)
    {
        for (;;)
        {    
            if (val1 == 0) return val2;
                val2 %= val1;
            if (val2 == 0) return val1;
                val1 %= val2;
        }
    } 
    
    // comparision operator overload 
    bool Fraction::operator==(const Fraction& rhs) const
    {
        Integer numCheck = this->_numerator;
        Integer denCheck = this->_denominator;
        if (rhs._numerator.getValue())
            numCheck.setValue(numCheck.getValue() / rhs._numerator.getValue());
        if (rhs._numerator.getValue())
            denCheck.setValue(denCheck.getValue() / rhs._denominator.getValue());
        if (numCheck == denCheck) {
            return true;
        }
        return false;
    }
    

QUESTION:

  1. I am confused as how to add Integer + Fraction class.
  2. Do I need to create another class which will inherit from Number class.
  3. How to overload oprator+ present in Number Class.

Suppose I try to add Integer + Fraction = Fraction in the Integer class itself then I will have something like Example

class Integer : public Number<Integer>
{
    const Fraction operator+(const Fraction &);
}
    const Fraction Integer::operator+(const Fraction &numberTwo)
{
                                              ^^ I will get error here           
    // Addition opeartion
}

Please help me.

回答1:

For your first question, the solution is to not use member function overloads, but to create a non-member function overload, e.g.

Fraction operator+(Integer const& integer, Fraction const& fraction)
{
    // Logic to add the integer and fraction here
    // Perhaps something like...
    Fraction f(integer.getValue(), 1);  // Create fraction
    return f + fraction;
}

The code above uses the Fraction::operator+ function to add the integer.



回答2:

While you can add an Integer+Fraction operator to your current design like Joachim suggested, that's going to result in some code duplication or at least some unnecessary boilerplate.

I suggest an alternative design instead: Make Integer convertible to Fraction. After all, any integer can be represented by the Fraction type, right?

You can make Integer convertible in two ways: By adding a conversion function to Integer, or by adding a converting constructor to Fraction.

I recommend choosing the converting constructor approach, because Fraction already depends on Integer type and so the cast operator would result in a circular dependency, just like your member operator attempt. I'll leave the implementation as an exercise.

This design requires that the addition operator is implemented as a non-member overload:

Fraction operator+(Fraction const& left, Fraction const& right)

With the converting constructor, this function can handle any combination of (F + F), (F + I) and (I + F).