C++ Rational Class with Constructors

How am I supposed to implement a second constructor that converts "void" to rational (where input == 1)? I am a beginner programmer working on an assignment for class. I got this rational number calculator to work on my own terms, but I have been told I have to write it like a.add(b) instead of result.add(a, b) like I orignally had it. I know that I need another constructor that only has one parameter, but I can't figure out how to do it. I hope I am not spamming code, I am just a lost coder trying to learn without any luck so far. I am going to have to make the other member functions work similarly. For example a.sub(b) instead of c.sub(a, b).

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
nclude <iostream>
#include <fstream>
#include <string>
#include <cmath>


using namespace std;

class Rational {
private:
	double n, d; // initialize numerator and denominator


public:
	Rational(double n = 0, double d = 1) : n(n), d(d) {}; //constructor to establish the fraction format

	void add(Rational b) { //member function for addition
		n = (n * b.d) + (b.n * d);
	    d = (d * b.d);
} 
	void sub(Rational a, Rational b) { //member function for subtraction
		n = (a.n * b.d) - (b.n * a.d);
		d = (a.d * b.d);
	}
	void mul(Rational a, Rational b) { //member function for multiplication
		n = (a.n * b.n);
		d = (a.d * b.d);
	}
	void div(Rational a, Rational b) { //member function for division
		n = (a.n * b.d);
		d = (a.d * b.n);
	}
	bool less(Rational a, Rational b) {
		if ((a.n / a.d) < (b.n / b.d)) {
	cout << "True";
}

else { 
	cout << "False";
}
return 0;
		

	}


	void neg(Rational a) { //member function for division
		n = -a.n;
		d = (a.d);
	}


	string display() {
		string na;
		cout << n << '/' << d;
		return na;

	}




};

int main() {

	int input;
	int n1, n2, d1, d2;

	cout << "Welcome to the Rational Number Operation Module (make a selection by entering the corresponding number): \n";
	cout << "1 - add\n";
	cout << "2 - sub\n";
	cout << "3 - mul\n";
	cout << "4 - div\n";
	cout << "5 - less than\n";
	cout << "6 - neg\n";
	cout << "7 - input (fetches numbers from a file)\n";
	cout << "8 - output (writes numbers to a file)\n";
	cin >> input;

	if (input == 1) {
		cout << "Please enter your first fraction (n1 d1): ";
		cin >> n1 >> d1;
		cout << "Please enter your second fraction (n2 d2): ";
		cin >> n2 >> d2;
		Rational a(n1, d1);
		Rational b(n2, d2);
		Rational result = a.add(b); //my error message is on this line, underlining a.
		cout << a.display();
		cout << '+';
		cout << b.display();
		cout << '=';
		cout << result.display();
	}
	if (input == 2) {
		cout << "Please enter your first fraction (n1 d1): ";
		cin >> n1 >> d1;
		cout << "Please enter your second fraction (n2 d2): ";
		cin >> n2 >> d2;
		Rational a(n1, d1);
		Rational b(n2, d2);
		Rational c; c.sub(a, b);
		cout << a.display();
		cout << '-';
		cout << b.display();
		cout << '=';
		cout << c.display();
	}
	if (input == 3) {
		cout << "Please enter your first fraction (n1 d1): ";
		cin >> n1 >> d1;
		cout << "Please enter your second fraction (n2 d2): ";
		cin >> n2 >> d2;
		Rational a(n1, d1);
		Rational b(n2, d2);
		Rational c; c.mul(a, b);
		cout << a.display();
		cout << '*';
		cout << b.display();
		cout << '=';
		cout << c.display();
	}
	if (input == 4) {
		cout << "Please enter your first fraction (n1 d1): ";
		cin >> n1 >> d1;
		cout << "Please enter your second fraction (n2 d2): ";
		cin >> n2 >> d2;
		Rational a(n1, d1);
		Rational b(n2, d2);
		Rational c; c.div(a, b);
		cout << a.display();
		cout << '/';
		cout << b.display();
		cout << '=';
		cout << c.display();
	}
	if (input == 5) {
		cout << "Please enter your first fraction (n1 d1): ";
		cin >> n1 >> d1;
		cout << "Please enter your second fraction (n2 d2): ";
		cin >> n2 >> d2;
		Rational a(n1, d1);
		Rational b(n2, d2);
		cout << a.display();
		cout << '<';
		cout << b.display();
		cout << '=';
		Rational c; c.less(a, b);
		//cout << a.less(a, b);
		
	}
	if (input == 6) {
		cout << "Please enter your first and only fraction (n1 d1): ";
		cin >> n1 >> d1;
		Rational a(n1, d1);
		Rational c; c.neg(a);
		cout << a.display();
		cout << '=';
		cout << c.display();
	}

	}

Last edited on
you are confusing constructors with your add, sub, etc methods.

your add for a.add(b) looks fine to me. I would put & on the parameter, its more efficient (avoids copying it).

you don't need a constructor to do the one parameter add/sub/etc functions.

Do you need a copy constructor for some reason? If you do, its a different topic from the math ones.

Side note, you can craft the actual + operator and so on so you can say c=a+b for your objects. But that can wait until you get what you have finished.

On line 88, I am getting an error message "no suitable constructor exists to convert "void" to "Rational". Basically my issue is that I wrote my own main function, but for the assignment I need to cater to a different main function. For example, the code below is a test case that I have to perform. I need to change my Rational class to cater to this part of the main function.

Rational ob3(1, 2);
Rational ob4(1, 4);
Rational result = ob3.add(ob4);cout << result.get_numerator() << "/" << result.get_denominator() << endl; // 6/8
oh. yes, a.add(b) returns a void, you see.
this is either a requirements miss or design flaw, but I think for now you are best off to just say
a.add(b);
rational result = a;
If there is syntax to do that in one line, its probably difficult to read.

another way to fix it would be to have add return *this as a rational, but .. did your requirements say void on those or not?
Last edited on
thank you for your answers, the member functions don't specify a void function, so do you think I would be better off making my add function look like this? Rational add(Rational &b)?
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
#include <iostream>
#include <string>

using namespace std;

class Rational
{
private:
    double n, d;
public:
    Rational(double n = 0, double d = 1) : n(n), d(d) {};
    
    Rational add(Rational b)
    {
        n = (n * b.d) + (b.n * d);
        d = (d * b.d);
        
        return Rational(n,d);
    }
    
    string display()
    {
        string na;
        cout << n << '/' << d;
        return na;
    }
};

int main()
{
    Rational a(1,2);
    Rational b(4,5);
    
    Rational answer = a.add(b);
    answer.display();
}


13/10
Program ended with exit code: 0

Perhaps something 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
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <iomanip>

using namespace std;

class Rational {
private:
	double n {}, d {}; // initialize numerator and denominator

public:
	Rational(double n = 0, double d = 1) : n(n), d(d) {}; //constructor to establish the fraction format

	Rational& add(Rational b) { //member function for addition
		n = (n * b.d) + (b.n * d);
		d = (d * b.d);
		return *this;
	}

	Rational& sub(Rational b) { //member function for subtraction
		n = (n * b.d) - (b.n * d);
		d = (d * b.d);
		return *this;
	}

	Rational& mul(Rational b) { //member function for multiplication
		n = (n * b.n);
		d = (d * b.d);
		return *this;
	}

	Rational& div(Rational b) { //member function for division
		n = (n * b.d);
		d = (d * b.n);
		return *this;
	}

	bool less(Rational b) {
		return (n / d) < (b.n / b.d);
	}

	Rational& neg() { //member function for negation
		n = -n;
		return *this;
	}

	void set(double n_, double d_) {
		n = n_;
		d = d_;
	}

	friend ostream& operator<<(ostream& os, const Rational& r) {
		return os << '(' << r.n << " / " << r.d << ')';
	}
};

int main() {
	for (unsigned input {}; input != 9; ) {
		cout << "\nWelcome to the Rational Number Operation Module (make a selection by entering the corresponding number): \n";
		cout << "\n1 - add\n";
		cout << "2 - sub\n";
		cout << "3 - mul\n";
		cout << "4 - div\n";
		cout << "5 - less than\n";
		cout << "6 - neg\n";
		cout << "7 - input (fetches numbers from a file)\n";
		cout << "8 - output (writes numbers to a file)\n";
		cout << "9 - quit\n";
		cout << "Enter option: ";
		cin >> input;

		Rational a;
		Rational b;
		int n1 {}, d1 {};

		if (input >= 1 && input <= 5) {
			cout << "Please enter your first fraction (n d): ";
			cin >> n1 >> d1;
			a.set(n1, d1);

			cout << "Please enter your second fraction (n d): ";
			cin >> n1 >> d1;
			b.set(n1, d1);
		}

		switch (input) {
			case 1:
				cout << a << " + " << b << " = " << a.add(b) << '\n';
				break;

			case 2:
				cout << a << " - " << b << " = " << a.sub(b) << '\n';
				break;

			case 3:
				cout << a << " * " << b << " = " << a.mul(b) << '\n';
				break;

			case 4:
				cout << a << " / " << b << " = " << a.div(b) << '\n';
				break;

			case 5:
				cout << a << " < " << b << " = " << boolalpha << a.less(b) << '\n';
				break;

			case 6:
				cout << "Please enter your first and only fraction (n d): ";
				cin >> n1 >> d1;
				a.set(n1, d1);

				cout << "Neg " << a << " = " << a.neg() << '\n';
				break;

			case 9:
				break;

			default:
				cout << "Invalid option\n";
				break;
		}
	}
}

thank you for your answers, the member functions don't specify a void function, so do you think I would be better off making my add function look like this? Rational add(Rational &b)?


'better off' depends on what you want to do with it, and how you want to use it. This is a problem with basic schoolwork: you build this fancy tool but you have no reason for it to exist nor any real use for it! So, you don't have a clear vision of how to use it to solve the problems you are working on, because you don't have a problem you are working on :)

Personally I would like to be able to say result = a+b. Pretend those are integers. Would YOU imagine that it is FRIENDLY to write code using integers where, to add a + b, A IS MODIFIED?
Ill cut that short: no, that sucks. More often than not in math code, you would need A again and its lost, or you had to stop to copy it first, which is annoying.
so if *I* were doing this thing, I would have R = A+B where A and B are untouched, and R has my answer. This has multiple good uses: you can chain it: R = (a.add(b)).add(c) because the result of a adding b is a rational object which as its OWN add function! This is kinda goofy looking but you can fix that with operator overloading so it really looks like R = A+B+C.

So, yes, I personally would have the add method return a new rational, and leave the operands untouched. This is how everything else works (like integers) ... and for a number of great reasons. There are exceptions... very large objects, like giant matrices, it IS useful to have 'destructive' operators that wipe the operand with the result, to save memory use -- as long as the operands are 'disposable' its fine.
Last edited on
As a C++ solution using operator overloading, consider:

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <iostream>
#include <iomanip>
#include <numeric>	// Note C++17 for gcd()

using namespace std;

class Rational {
private:
	int n {}, d {1}; // initialize numerator and denominator

	Rational& simplfy() {
		const auto cd {std::gcd(n, d)};

		if (cd > 1) {
			n /= cd;
			d /= cd;
		}

		return *this;
	}

public:
	Rational(int n_ = 0, int d_ = 1) : n(n_), d(d_) {};		//constructor to establish the fraction format

	Rational operator+(const Rational& b) const {
		Rational t(*this);

		return t += b;
	}

	Rational operator-(const Rational& b) const {		//member function for subtraction
		Rational t(*this);

		return t -= b;
	}

	Rational operator*(const Rational& b) const {		//member function for multiplication
		Rational t(*this);

		return t *= b;
	}

	Rational operator/(const Rational& b) const {		//member function for division
		Rational t(*this);

		return t /= b;
	}

	bool operator<(const Rational& b) const {
		return ((n + 0.0) / d) < ((b.n + 0.0) / b.d);
	}

	Rational operator~() const {	// Invert fraction
		return Rational(d, n);
	}

	bool operator==(const Rational& b) const {
		return b.n == n && b.d == d;
	}

	Rational operator-() const { //member function for negation
		return Rational {-n, d};
	}

	Rational& operator+=(const Rational& b) {
		n = (n * b.d) + (b.n * d);
		d = d * b.d;
		return simplfy();
	}

	Rational& operator-=(const Rational& b) {
		n = (n * b.d) - (b.n * d);
		d = d * b.d;
		return simplfy();
	}

	Rational& operator*=(const Rational& b) {
		n = n * b.n;
		d = d * b.d;
		return simplfy();
	}

	Rational& operator/=(const Rational& b) {
		*this *= ~b;
		return simplfy();
	}

	friend ostream& operator<<(ostream& os, const Rational& r) {
		return os << '(' << r.n << " / " << r.d << ')';
	}
};

int main() {
	for (unsigned input {}; input != 9; ) {
		cout << "\nWelcome to the Rational Number Operation Module (make a selection by entering the corresponding number): \n";
		cout << "\n1 - add\n";
		cout << "2 - sub\n";
		cout << "3 - mul\n";
		cout << "4 - div\n";
		cout << "5 - less than\n";
		cout << "6 - neg\n";
		cout << "7 - input (fetches numbers from a file)\n";
		cout << "8 - output (writes numbers to a file)\n";
		cout << "9 - quit\n";
		cout << "Enter option: ";
		cin >> input;

		Rational a;
		Rational b;
		int n1 {}, d1 {};

		if (input >= 1 && input <= 5) {
			cout << "Please enter your first fraction (n d): ";
			cin >> n1 >> d1;
			a = Rational(n1, d1);

			cout << "Please enter your second fraction (n d): ";
			cin >> n1 >> d1;
			b = Rational(n1, d1);
		}

		switch (input) {
			case 1:
				cout << a << " + " << b << " = " << a + b << '\n';
				break;

			case 2:
				cout << a << " - " << b << " = " << a - b << '\n';
				break;

			case 3:
				cout << a << " * " << b << " = " << a * b << '\n';
				break;

			case 4:
				cout << a << " / " << b << " = " << a / b << '\n';
				break;

			case 5:
				cout << a << " < " << b << " = " << boolalpha << (a < b) << '\n';
				break;

			case 6:
				cout << "Please enter your first and only fraction (n d): ";
				cin >> n1 >> d1;

				a = Rational(n1, d1);

				cout << "Neg " << a << " = " << -a << '\n';
				break;

			case 9:
				break;

			default:
				cout << "Invalid option\n";
				break;
		}
	}
}

Topic archived. No new replies allowed.