Overloading functions and operators

  • Overloading functions:
    Basically, C++ allows to use the same function name for different functions. This is especially useful when having differences only in the type of arguments, but otherwise very similar functionality. As an example, consider:
    void swap(int & x,int & y) {
        int temp = x;  x = y;  y=temp; }

    void swap(double & x,double & y) {
        double temp = x;  x = y;  y=temp; }

    int main() {
        int m,n;
        m = 3; n = 5;
        swap (m,n);

        double s,t;
        s = 3.14; t = 2.71;
        swap (s,t);
    }


    Of course you could overload wildly different functions with the same name. However, this isn't tremendously sensible.
  • Overloading operators:
    Since at the end of the day operators (like "+") are just functions, they can be overloaded as well. As an example consider a class "Ratio":
    #include <iostream.h>

    class Ratio {
    private:
        int numerator, denominator;
    public:
        Ratio(int,int);
        Sum(Ratio,Ratio);
        Ratio operator+(int);
        Ratio operator+(Ratio);
        friend Ratio operator+(int,Ratio);
        friend ostream & operator<<(ostream &, const Ratio &);
    }

    Ratio::Ratio(int num,int den) {
        numerator = num;
        denominator = den;
    }

    Ratio::Sum(Ratio sum1,Ratio sum2) {
        int num = sum1.numerator * sum2.denominator +
              sum2.numerator * sum1.denominator;
        int den = sum1.denominator * sum2.denominator;
        return Ratio(num,den);
    }

    Ratio::operator+(int sum2) {
        numerator += sum2 * denominator;
        return (*this);
    }

    Ratio::Ratio operator+(Ratio sum2) {
        numerator = numerator * sum2.denominator +
              sum2.numerator * denominator;
        denominator *= sum2.denominator;
        return (*this);
    }

    Ratio operator+(int sum1,Ratio sum2) {
        int num = sum1 * sum2.denominator + sum2.numerator;
        int den = sum2.denominator;
        return Ratio(num,den);
    }

    ostream & operator<<(ostream & ostr,const Ratio & r) {
        if (r.denominator = 1) ostr << r.numerator << endl;
        else ostr << r.numerator << "/" << r.denominator << endl;
        return ostr;
    }


    A few things are to be noted here:
    • I have separated the declarations of methods inside the class a little bit from their explicit realizations. Any method that is a class member and that is realized outside the class declaration is then linked to this class by Ratio::.
    • The method Sum and the overloaded operator+ have exactly the same functionality. However, it seems to me that the usage of "+" looks more natural.
    • Remember the difference between private and public. To make sure that your overloaded operators outside the class can access the private data, numerator and denominator you have to add "friend" in front of it.
    • The overloaded operators with two arguments are no members of the class declaration whereas the overloaded operator with only one argument is part of the class. The reason is as follows:
      • In case the compiler runs into an operator it checks the type of the object before and after the operator. Then it looks for the definition of this operator in the class definition of the object before the operator. Obviously, expressions of the form Ratio + Ratio can then be found in the class Ratio.
        If this is the case, the object before will be equipped with the operator and the object after the operator as its argument. In some sense, the first object is then given by the default and pointing on itself, the operator being just an ordinary method of the class. Therefore, you might just modify the data of the object before the operator and return it.
      • The reasoning above breaks down, if you want to add a Ratio from the right to an integer, since the intrinsic integer definition of C++ knows nothing about your class Ratio. Then the operator is not just a member of the class Ratio.
    • The this operator points on the instantiated class member under actual consideration.
    • To overload the output operator >> you have to pass the output stream as well. This stream contains for instance the device for the output (and other information about formats etc.).


    [prev] [top] [next]