Most modern compilers support something known as the return value optimisation.

this

Code:

Rational operator*(const Rational & lhs, const Rational & rhs)
{
Rational result;
result.numerator = lhs. numerator * rhs.numerator;
result.denominator = lhs.denominator * rhs.denominator;
return result;
}

is better written as:-

Code:

Rational operator*(const Rational& lhs,const rational& rhs)
{
return Rational ((lhs.numerator*rhs.numerator),(lhs.denominator*rhs.denominator));
}

This eliminates the otherwise needed temporary.