Yes, it's getters and setters. You should use them instead of a friend function because people are anal and will ***** at you if you use friend functions...seriously, friend functions violate information hiding and the whole OOP thing (at least most say so), so using getters and setters is a better idea...sometimes a friend function would simplify things though.
Okay, so you have a fractions function that can be intialized with a numerator and denominator or with just a numerator (you would make the denom default to 1 in the implementation).
rational(int num); //just initialize num
rational(int num, int denom); //initialize num and denom
blah blah blah...
now you have a top-level function that takes two rationals.
const rational operator+(rational first, rational second) //my best guess at this
Now you do '2 + rational' of course the scond rational works, but the first is an int...so your screwed...no, wait...the compiler knows if it supplies an int to the rational constructor it can make a rational. So it does and your all set. The same works for 'rational + 2'. You could also make a conversion operator function.
The compiler will only do conversions on both args if it's a top level function.
Anyway...sorry I'm not much of an explainer. And sorry if the code is screwed up. I don't really program. But hopefully you get the idea.