I started to learn C++ recently and as a starter was asked to design a class for fractions which can do *,+,- and / . This is the class that I designed. Are there any flaws in the design? Can anybody please help me?
#include <iostream>
#include <stdexcept>
usingnamespace std;
class Fraction
{
int numerator;
int denominator;
public:
Fraction() // Default constructor
{
numerator = 0;
denominator = 1;
}
Fraction(int n,int d) // parameterized constructor
{
numerator = n;
if(d==0)
{
cout<<"Divide by zero error : Fraction Created as 0/1 \n";
numerator = 0;
denominator = 1;
}
else
denominator = d;
//Alternatively this can be used depending on if we want the program to be terminated in case of bad input
/*try
{
if(d==0)
throw std::overflow_error("Divide by zero exception");
else
{
numerator = n;
denominator = n;
}
}
catch(std::overflow_error& e)
{
cout<<e.what();
}*/
}
Fraction(const Fraction& other) // copy constructor
{
numerator = other.numerator;
denominator = other.denominator;
}
void reduce(Fraction& fract) // Function for reducing the fraction
{
int gcd = gcdr(fract.numerator,fract.denominator);
if(gcd!=1)
{
fract.numerator = fract.numerator/gcd;
fract.denominator = fract.denominator/gcd;
}
}
int gcdr ( int a, int b ) // Function for finding GCD of two numbers : Used for reducing
{
if ( a==0 )
return b;
return gcdr ( b%a, a );
}
int lcm(int a, int b) // Function for finding LCM of two numbers : Used while addition and subtraction
{
int temp = gcdr(a, b);
return temp ? (a / temp * b) : 0;
}
Fraction multiply(Fraction other) // Function for multiplying two fractions
{
Fraction result;
result.numerator = numerator * other.numerator;
result.denominator = denominator * other.denominator;
reduce(result);
return result;
}
Fraction inverse(Fraction other) // Function for inversing a fraction : Used during division
{
Fraction result(other.denominator, other.numerator);
return result;
}
Fraction divide(Fraction other) // Function for dividing two fractions
{
Fraction result;
result = multiply(inverse(other));
return result;
}
Fraction add(Fraction other) // Function for adding two fractions
{
Fraction result;
int lcm_value = lcm(denominator,other.denominator);
result.numerator =( numerator*lcm_value/denominator + other.numerator * lcm_value/other.denominator );
result.denominator = lcm_value;
reduce(result);
return result;
}
Fraction subtract(Fraction other) // Function for subtracting two fractions
{
Fraction result;
int lcm_value = lcm(denominator,other.denominator);
result.numerator =( numerator*lcm_value/denominator - other.numerator * lcm_value/other.denominator );
result.denominator = lcm_value;
reduce(result);
return result;
}
bool is_equal(Fraction a)
{
int lcm_value = lcm(denominator,a.denominator);
if ( (numerator*lcm_value/denominator) == (a.numerator * lcm_value/a.denominator))
returntrue;
elsereturnfalse;
}
bool is_greater_than(Fraction a)
{
int lcm_value = lcm(denominator,a.denominator);
if ( (numerator*lcm_value/denominator) > (a.numerator * lcm_value/a.denominator))
returntrue;
elsereturnfalse;
}
void print_fraction() // Function for printing the fraction
{
cout<<numerator<<'/'<<denominator<<endl;
}
~Fraction()
{
cout<<"Destroying objects\n";
}
};
You're showing an implementation, not a design document. Working back to what the design might have been , I would ask why is the public interface so unusual for a value-semantic type: it is neither equality-comparable nor less-then-comparable, and therefore can't be used with standard C++ containers and algorithms. I would also recommend removing the copy ctor and dropping surprise output statements from ctor and dtor (at which time dtor can be removed too). Of course you're not showing the specs, so it's possible that this output is a requirement, but if it's just to implement the mathematical fraction type, take a look at std::complex for design ideas.
I think code wise its pretty well designed. To full advantage of the language though I would use operator+, operator-, operator*, operator/, operator<, operator>, operator==, and operator>> instead of the alternate Java function names add, subtract...etc.
Look up operator overloading. I think you'll like the feature but remember to employ those features in moderation. In this case I would think it would be appropriate though.