C++ operator overloading for rationalNumber I have created a rationalnumber class and used operator overloading function of C++.

My questions are:


Have I implemented the class and &lt; operator correctly?
Objects of class can now inserted in map and set. Is that part done correctly?




#include &lt;bits/stdc++.h&gt;
using namespace std;

class RationalNumber {
    int num;
    int den;
    bool negative;
    int gcd(int a, int b) {
        if (b == 0)
            return a;
        return gcd(b, a % b);
    }
public:
    RationalNumber() {
        num = den = 1;
        negative = 0;
    }
    RationalNumber(int a, int b) {
        if ((a &lt; 0) ^ (b &lt; 0))
            negative = 1;
        else
            negative = 0;
        num = abs(a);
        den = abs(b);
        int h = gcd(a, b);
        num /= h;
        den /= h;
    }
    RationalNumber operator+(const RationalNumber &amp;r) {
        RationalNumber added;
        added = RationalNumber(num * r.den + r.num * den, den * r.den);
        return added;
    }
    bool operator&lt;(const RationalNumber &amp;r) const {
        return num * r.den &lt; r.num * den;
    }

    void toString() {
        cout &lt;&lt; num &lt;&lt; "/" &lt;&lt; den &lt;&lt; endl;
    }
};
int main(int argc, char **argv) {
    RationalNumber r1(3, 5);
    RationalNumber r2(1, 3);
    RationalNumber r3 = r1 + r2;
    RationalNumber r4(9, 13);
    vector&lt;RationalNumber&gt; v;
    map&lt;RationalNumber, string&gt; S;
    map&lt;RationalNumber, string&gt;::iterator it;
    S[r1] = "1";
    S.insert(S.begin(), pair&lt;RationalNumber, string&gt;(r2, "2"));
    S.insert(S.begin(), pair&lt;RationalNumber, string&gt;(r2, "2"));
    S.insert(S.begin(), pair&lt;RationalNumber, string&gt;(r3, "3"));
    S.insert(S.begin(), pair&lt;RationalNumber, string&gt;(r4, "4"));
    for (it = S.begin(); it != S.end(); ++it) {
        RationalNumber r = it-&gt;first;
        r.toString();
        cout &lt;&lt; it-&gt;second &lt;&lt; endl;
    }
    return 0;
}
Style:


Use an initialiser list for constructors, with meaningful parameter names. example at the end.
Please use the right type for negative - true/false makes it a lot easier to read and understand inline what type negative is.
Naming: The toString() is easier expressed by returning a std::string - that can be used as-is or forwarded to std::cout or other logs. If you want to use a log output, (e.g. std::cout) it can be trivially implemented using a template operator&lt;&lt; with a generic ostream input - in this case it is not required (see below)
The operator+ can be expressed in a single line, without the temporary added variable.
it is desirable to make gcd an non-member file-local static function (static gcd(int a, int b)) the rationale being that the logic:


doesn't depend on the state (or const-ness) of the Rational object (so non-member)
doesn't need to access the (private/protected) innards of Rational(so non-static, non-friend)

In main, the for loop can be shortened (in general, if a function call chain helps avoid a temp variable, do so). example at the end.


The same logic (avoiding a temp variable) holds for defining r3 and r4 inlined when adding them to the map. 


vector v is unused.
Include what you use: vector, map, iostream, cmath (and iterator if you decide to use ostream_iterator.
maps don't require an input iterator during insertion. Use std::make_pair(a, b) to cut down on the verbose template boilerplate.


Logical Issues:


Translation into abs and negative is done in the ctor and not followed up well in other places. This will fail for negative test cases. hint: why is negative required as a member?
adding 1/4 and 1/2 results in 6/8 - while this isn't incorrect, this defeats the purpose. Invoke gcd there.
Depending on how you want your object to behave, handle the case of (den == 0), either by explicity asserting against its occurence, or by adding special handling for arithmetic operators. You don't want a 1/0 + 5/2 == 2/0 comparison.


Constructor style preferred:

RationalNumber() : num(1), den(1), negative(false) {}
RationalNumber(int numerator, int denominator) 
: num(abs(numerator))
, den(abs(denominator))
, negative((numerator &lt; 0) == (denominator &lt; 0)) 
{
    //use gcd here
}


Terser loop style suggestions:

for (map&lt;RationalNumber, string&gt;::iterator it = S.begin(); it != S.end();++it) 
{
    std::cout &lt;&lt; "comparing:" &lt;&lt; itr-&gt;first.toString() &lt;&lt; itr-&gt;second &lt;&lt; std::endl;
}


or the even terser lambda:

transform(S.begin(), S.end(), ostream_iterator&lt;string&gt;(cout, '\n'), 
    [] (const pair&lt;RationalNumber, string&gt;&amp; p) { return p.first.toString() + " " + p.second; });


edits: 
Moved code examples to the end - as code indents don't work in between bulleted points.