Constructor help C++

SIM0N

Junior Member
Nov 24, 2012
8
0
0
I am working on a program that uses a custom class for performing arithmetic equations on rational numbers. I will end with functions that multiply, divide, add, and subtract rationals, and store the answers in simplest form.

Everything is going okay so far except for one thing. I need and have a custom default constructor to set the values for any Rational.object that may not be given a value when instantiated.

Example is

Rational answer();

This creates the answer object of type Rational. With my custom constructor it is supposed to store a numerator at 0 and a denominator at 1. However when I attempt to create an object without passing any value and then attempt to use that object on the left side of an equation it yells at me.

Here is my code for the header file:
Code:
#ifndef RATIONAL_H
#define RATIONAL_H

class Rational
{

public:
    Rational();
    Rational(int, int);
    void print_Rational();
    Rational multiply_Rationals(Rational);
private:
    int numerator;
    int denominator;
};

#endif

and here is my code for the client and member functions:
Code:
#include <iostream>
#include <iomanip>
#include "Rational.h"

using namespace std;

Rational::Rational()
{                    
numerator = 0;
denominator = 1;
};

Rational::Rational(int n, int d)
{
    int max;
    Rational result;
    (n>d) ? max = n:max = d;
    for(int i=2;i<=max/2;i++)
    {
        if(n%i ==0 && d%i ==0)
	    {
            numerator = n/i;
            denominator = d/=i;
        }
    }
};

Rational Rational::multiply_Rationals(Rational second_rational)
{
    int num_Result;
    int den_Result;
    Rational results(0,1);
    num_Result = ( numerator * second_rational.numerator );
    den_Result = ( denominator * second_rational.denominator );
    Rational(num_Result, den_Result);
    results.numerator = num_Result;
    results.denominator = den_Result;
    return Rational(results.numerator, results.denominator);
}

void Rational::print_Rational()
{ 
    cout << numerator << "/" << denominator << endl;
}     

int main()
{
 Rational f1(7,14);
 Rational f2(4,6);
 Rational answer(0,1);
 answer = f1.multiply_Rationals(f2);
 f1.print_Rational();
 cout << "Times " << endl;
 f2.print_Rational();
 cout << "equals" << endl;
 answer.print_Rational();
 system("PAUSE");
}

Now as you can see I create a Rational object in the multiply_Rationals function called 'results' and another Rational object in the main called 'answer'.
The program runs fine now, but I would like to omit the values that I am passing into those two objects and have the custom constructor that I made set the objects to their default values. When I take out the values that I am passing in though it bombs. Any thoughts???
 
Last edited:

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
I don't see anything wrong at first glance.

How are you creating the variables?

Rational answer();

or

Rational answer;

?
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
This is a giveaway, but I can't think of a way to just hint at the answer.
Try this:
Code:
[spoiler]
Rational Rational::multiply_Rationals(Rational second_rational) {
  int num_Result = numerator * second_rational.numerator;
  int den_Result = denominator * second_rational.denominator;
  return Rational(num_Result, den_Result);
}
[/spoiler]
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,835
4,815
75
By the way, that's a terrible way to find the simplest form of a rational. A better way has been known for thousands of years. I'm surprised your teacher didn't bring it up.
 

SIM0N

Junior Member
Nov 24, 2012
8
0
0
This is a giveaway, but I can't think of a way to just hint at the answer.
Try this:
Code:
[spoiler]
Rational Rational::multiply_Rationals(Rational second_rational) {
  int num_Result = numerator * second_rational.numerator;
  int den_Result = denominator * second_rational.denominator;
  return Rational(num_Result, den_Result);
}
[/spoiler]


That is a nifty way to code that function where it doesn't require the empty constructor call but I still need to be able to create an object without any parameters and have the program call the empty constructor.
 

iCyborg

Golden Member
Aug 8, 2008
1,387
94
91
Can you describe how are you trying to do it?
I don't see what is the problem with having:
Code:
Rational a;
a.print_Rational();

Btw, it's kind of redundant and odd to have the class name in the names of every function: print_Rational, multiply_Rationals etc.
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
Have default parameters setup for the constructor

Rational (int n=0, int d = 1)
{
}
 

iCyborg

Golden Member
Aug 8, 2008
1,387
94
91
Default params is a good idea here, but it won't help him. I think he may be trying to instantiate default Rational as:

Rational a(); // this declares a function returning Rational, not a Rational object with default params!

instead of 'Rational a;'

Though brandonb's post should have given him this clue...
 

SIM0N

Junior Member
Nov 24, 2012
8
0
0
Back again, stopped worrying about that problem till I had everything written that I needed. Just revisited it and got back on here and that is exactly what the problem was. I was declaring it as a function and not an object. Fixed that and it works like a charm now. Thank all of you for your help.

Still working through the function for simplifying, which I have read is poorly written.

Also having an issue with converting the fractions to floating point... a problem like I have no idea how to do that. I don't even know if this is right but I'm trying to just return the result the numerator divided by the denominator, and the result keeps coming up as zero.

I've tried storing that result as a double, or a float and it doesn't work.

According to my sample attempt: 1 divided by 6 equals 0.
 

iCyborg

Golden Member
Aug 8, 2008
1,387
94
91
When you divide two integers, the result is an integer, so yes, 1/6 = 0 for ints. If you store that into a double, it's already late, you have to convert (at least one of the operands) to a double before dividing.

E.g. try this:
double realNum = double(numerator)/denominator;
 

SIM0N

Junior Member
Nov 24, 2012
8
0
0
Well that one wasn't that bad now was it? :)

Now I almost have everything completed. The last step I am working on is the simplification process. I have now moved on to determining the greatest common divisor. Then dividing both the numerator and the denominator by that. This is working fine except in the case of improper fractions and negative fractions.

I have been dividing the numerators and denominators within the multiply/divide/add/subtract functions and as you can see, when the fraction are either negative or improper, i get the craziest results.

Here is my code:
Code:
#include <iostream>
#include <iomanip>
#include "Rational.h"

using namespace std;

//Constructor
Rational::Rational()
{                    
numerator = 0;
denominator = 1;
};

//Overloaded-Constructor
Rational::Rational(int n, int d)
{
numerator = n;
denominator = d;

};

//Returns GCD
int Rational::gcd(int n,int d)
{
  if(d != 0)
  {gcd(d, n%d);}
  return n;
}



Rational Rational::multiply(Rational second_rational)
{
    int num_Result;
    int den_Result;
    Rational results;
    num_Result = (numerator * second_rational.numerator);
    den_Result = (denominator * second_rational.denominator);

    
    results.numerator = num_Result/gcd(num_Result, den_Result);
    results.denominator = den_Result/gcd(num_Result, den_Result);
    return results; 
}

Rational Rational::divide(Rational second_rational)
{
    int num_Result;
    int den_Result;
    Rational results;
    num_Result = (numerator * second_rational.denominator);
    den_Result = (denominator * second_rational.numerator);
    
    results.numerator = num_Result/gcd(num_Result, den_Result);
    results.denominator = den_Result/gcd(num_Result, den_Result);
    return results; 
}

Rational Rational::add(Rational second_rational)
{
    int num_Result;
    int den_Result;
    Rational results;
    num_Result = (numerator * second_rational.denominator) + (denominator * second_rational.numerator);
    den_Result = (denominator * second_rational.denominator);
    
    results.numerator = num_Result/gcd(num_Result, den_Result);
    results.denominator = den_Result/gcd(num_Result, den_Result);
    return results; 
}

Rational Rational::subtract(Rational second_rational)
{
    int num_Result;
    int den_Result;
    Rational results;
    num_Result = (numerator * second_rational.denominator) - (denominator * second_rational.numerator);
    den_Result = (denominator * second_rational.denominator);
    
    results.numerator = num_Result/gcd(num_Result, den_Result);
    results.denominator = den_Result/gcd(num_Result, den_Result);
    return results; 
}


void Rational::print_Rational()
{ 
    cout << numerator << "/" << denominator;
}     


void Rational::print_Floating()
{ 
    double n = 0;
    double d = 0;
    double number;
    n = numerator;
    d = denominator;
    number = n/d;
    cout.setf(ios::fixed); 
    cout << setprecision(2) << number << endl;
}     

int main()
{
 Rational f1(50, 100);
 Rational f2(40, 100);
 Rational answer;
 
 //Prints multiply funtion results
 answer = f1.multiply(f2);
 f1.print_Rational();
 cout << " X ";
 f2.print_Rational();
 cout << " = ";
 answer.print_Rational();
 cout << endl;
 cout << "The decimal version of this is ";
 answer.print_Floating();
 cout << endl;
 
 //Prints divide funtion results
 answer = f1.divide(f2);
 f1.print_Rational();
 cout << " / ";
 f2.print_Rational();
 cout << " = ";
 answer.print_Rational();
 cout << endl;
 cout << "The decimal version of this is ";
 answer.print_Floating();
 cout << endl;
 
 //Prints add funtion results
 answer = f1.add(f2);
 f1.print_Rational();
 cout << " + ";
 f2.print_Rational();
 cout << " = ";
 answer.print_Rational();
 cout << endl;
 cout << "The decimal version of this is ";
 answer.print_Floating();
 cout << endl;
  
 //Prints subtract funtion results
 answer = f1.subtract(f2);
 f1.print_Rational();
 cout << " - ";
 f2.print_Rational();
 cout << " = ";
 answer.print_Rational();
 cout << endl;
 cout << "The decimal version of this is ";
 answer.print_Floating();
 cout << endl;
 
 system("PAUSE");
}


and here is the code for the header file:
Code:
#ifndef RATIONAL_H
#define RATIONAL_H

class Rational
{

public:
    Rational();
    Rational(int, int);
    void print_Rational();
    void print_Floating();
    Rational multiply(Rational);
    Rational divide(Rational);
    Rational add(Rational);
    Rational subtract(Rational);
private:
    void simplify(int, int);
    int gcd(int, int);
    int numerator;
    int denominator;
};

#endif
 

mv2devnull

Golden Member
Apr 13, 2010
1,539
169
106
First, there is a thing called initialization list that does not hurt to learn
Code:
Rational::Rational( int n, int d )
 : numerator( n ), denominator( d )
{ }
It does not help your code, but is still fun.


Then the beef, what does happen here, really?
Code:
int Rational::gcd(int n,int d)
{
 if(d != 0)
  {
   gcd(d, n%d);
  }
 return n;
}
In either case, you do return value of n, be there recursion or not. I presume that your compiler does not warn about a function returning a value and you doing nothing with it?

Ohh, how I like the way the Not So Short Introduction to LaTeX says: "Danger, Will Robinson! Danger!" ;)


Another style consideration:
Code:
Rational Rational::multiply( Rational second_rational )
{
  int num_Result;
  int den_Result;
  Rational results;
  num_Result = (numerator * second_rational.numerator);
  den_Result = (denominator * second_rational.denominator);
  results.numerator = num_Result/gcd(num_Result, den_Result);
  results.denominator = den_Result/gcd(num_Result, den_Result);
  return results;
 }
C requires to declare variables up front. C++ allows it and in a way it is descriptive, but they can be as well declared when used for the first time (if scopes allow).

More importantly, can you spot a potential efficiency issue in foo()?
Code:
int veryExpensiveBar( int gaz )
{ // a pure function with a very long computation
 ...
 return value;
}

Rational foo( int n )
{
  int a = veryExpensiveBar( n );
  int b = veryExpensiveBar( n );
  int c = veryExpensiveBar( n );
  int d = veryExpensiveBar( n );

  return Rational( a+b, c+d );
}