Member Function Within a Member Function

I have this project I am working on, and I'm trying to implement a function within a function just to make the code nicer, since the embedded function needs to be run at least 4 times.

Here is the essential information on the class:
1
2
3
4
5
6
7
8
9
10
11
  class fraction{
public:
    fraction(); //default
    fraction (int, int);  //parametrized constructor
    //observer functions
    fraction MultipliedBy(fraction);
    fraction fractionReduction(fraction)const;
private:
    int numerator;
    int denominator;
};


The reason fractionReduction is constant is because there is another function I need to implement it in that must be a constant.

The functions are as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
fraction fraction::fractionReduction(fraction temp)const   //finding and dividing by greatest common multiple
{
    fraction temp1;
    
    for (int i=1; i<temp.numerator*temp.denominator; i++)
    {
        if (temp.numerator%i==0 && temp.denominator%i==0){
            temp1.numerator=temp.numerator/i;
            temp1.denominator=temp.denominator/i;
        }
        
    }
    return temp1;
}


fraction fraction::MultipliedBy(fraction otherfraction)
{
    fraction temp, temp1;
    temp.numerator=numerator*otherfraction.numerator;
    temp.denominator=denominator*otherfraction.denominator;
    
    //finding and dividing by greatest common multiple
  
    temp1.fractionReduction(temp);
    
    return temp1;
}

My problem is this: within fractionReduction, after all the operations are done, it yields the right answer (I've checked). I am struggling to get that value to return into MultiplyBy, which will then be returned to main.

The private values are initialized in a constructor as numerator=0 and denominator=1, which is what is being outputted by the end of MultipliedBy.
Last edited on
What is your assignment all about? Can you give us an example?
Essentially, we are given a client file that tests our use of a single class and the member functions within it. As a numerical example, I am given 9/8 and 2/3, asked to multiply them, and then reduce them into a simplified fraction.

The part of the client file I am accessing with this code is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

fraction f1(9,8); //calling a parameterized class constructor
fraction f2(2,3);
fraction result; //calling a default class constructor
const fraction f3(12, 8);
const fraction f4(202, 303);


cout << "The product of ";
f1.showFraction();
cout << " and ";
f2.showFraction();
cout << " is ";
result = f1.MultipliedBy(f2); //a class binary operation - a value-returning "observer" function
result.showFraction();
cout << endl;


And showFraction is simply:
1
2
3
4
void fraction::showFraction()const
{
    cout<<numerator<<"/"<<denominator;
}


f3 and f4 are not used here, but I figured I should present them to help clear up why I'm using const for fractionReduction.

I really could just copy/paste the fractionReduction function into MultipliedBy with some variable modifications and get the result I want (and I have), but I really want to do this correctly. I just can't figure out how to get those values to move around the way I need them to.

Let me know if there is anything else I can clarify, or I can just post the whole assignment if it is still too vague.
Last edited on
1. what is the role of the fraction object that invokes the fractionReduction() methods? It's data-members are not used anywhere in the definition of this method. You're correct though in returning by value, and not reference, as it is a local object. The program below uses the invoking object's data members instead of declaring two new variables of type fraction (temp, temp1 in your program)
2. instead of MultipliedBy() a more elegant solution would be to overload the multiplication operator and since we could do a*b and b*a the overloaded operator is defined as a friend function, not class method, to cover all eventualities
3. similar to above point, let's overload the insertion operator instead of showFraction()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include<iostream>
#include<cmath>
using namespace std;

class fraction
{
    public:
        fraction(): numerator(0), denominator (1){}; //default
        fraction (const int& num, const int&  denom): numerator(num), denominator(denom) {};  //parametrized constructor
        fraction fractionReduction()const;
        friend fraction operator * (const fraction& lhs, const fraction& rhs);
        friend ostream& operator << (ostream& os, const fraction& rhs);
    private:
        int numerator;
        int denominator;
};
int gcd(const int& num, const int& den);//greatest common denominator;

int main()
{
    fraction f1(9,8), f2(2,3), f3(12, 8), f4(202, 303);
    cout<<f4*f1;
    cout<<f1*f4;
}
int gcd(const int& numerator, const int& denominator)
{
    if(denominator == 0)
    {
       return numerator;
    }
    else
    {
        return gcd(denominator, fmod(numerator, denominator));
    }
}
fraction fraction::fractionReduction() const   //finding and dividing by greatest common multiple
{
    fraction temp1;
    temp1.numerator = numerator/gcd(numerator, denominator);//division with gcd => no missing remainders
    temp1.denominator = denominator/gcd(numerator, denominator);

    return temp1;
}

fraction operator * (const fraction& lhs, const fraction& rhs)
{
    fraction temp1;
    temp1.numerator = (lhs.numerator )* (rhs.numerator);
    temp1.denominator = (lhs.denominator ) * (rhs.denominator);

    fraction temp2;
    temp2.numerator = temp1.numerator/gcd(temp1.numerator, temp1.denominator);
    temp2.denominator = temp1.denominator/gcd(temp1.numerator, temp1.denominator);

    return temp2;
}

ostream& operator << (ostream& os, const fraction& rhs)
{
	if(rhs.numerator == rhs.denominator)
    {
        os<<1<<"\n";
    }
    else
    {
        os<<rhs.numerator<<"/"<<rhs.denominator<<"\n";
    }
    return os;
}




Use a lambda function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fraction::multipliedBy(fraction temp)
{
   fraction temp1;

   auto fractionReduction = ()[&] //pass temp by reference
   {
          // do fraction reduction, use temp;
    }

   //do multiplication

   fractionReduction(); //since the captor is by reference, variables used inside the lambda function will be modified
   return temp1;

}
Last edited on
f3 and f4 are not used here, but I figured I should present them to help clear up why I'm using const for fractionReduction.

You could just call fractionReduction() in the constructor so that, fractions will always be proper when instantiated.

fraction fractionReduction() const;
Having the member function as const is misleading, as you're telling to the coder that you will not modify member variables, but the function name says otherwise.

temp1.fractionReduction(temp);
Note that fractionReduction() returns a fraction object, but you aren't assigning it to a variable. This is equivalent to doing something like: 100; // does nothing

Consider implementing fractionReduction() like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// helper function
// https://en.wikipedia.org/wiki/Euclidean_algorithm#Background:_greatest_common_divisor
int gcd( int a, int b )
{
    while( b != 0 ) {
        int t{ b };
        b = a % b;
        a = t;
    }

    return a;
}

// this will modify the caller's member variables
// so that you can call it like so
// fraction f1{ 20, 50 };
// does stuff with f1...
// f1.fractionReduction( );
void fraction::fractionReduction( )
{
    int gcd_{ gcd( numerator, denominator ) };
    numerator /= gcd_;
    denominator /= gcd_;
}
Last edited on
Topic archived. No new replies allowed.