Previous sections presented abridged versions of the fraction class and many of its functions as examples of overloaded operators, implemented as either member or friend functions. This section presents a complete, elaborated example, organized into multiple figures to simplify the presentation.
#pragma once
#include <iostream>
using namespace std;
class fraction
{
private:
int numerator; // (a)
int denominator;
public:
fraction(int n = 0, int d = 1); // (b)
friend fraction operator+(fraction f1, fraction f2); // (c)
friend fraction operator-(fraction f1, fraction f2);
friend fraction operator*(fraction f1, fraction f2);
friend fraction operator/(fraction f1, fraction f2);
friend ostream& operator<<(ostream& out, fraction& f); // (d)
friend istream& operator>>(istream& in, fraction& f);
private:
void reduce(); // (e)
int gcd(int, int);
};
friend keyword only appears in the specification.
#include <iostream>
#include "fraction.h"
using namespace std;
fraction::fraction(int n, int d) : numerator(n), denominator(d)
{
reduce();
}
fraction operator+(fraction f1, fraction f2)
{
int n = f1.numerator * f2.denominator +
f2.numerator * f1.denominator;
int d = f1.denominator * f2.denominator;
return fraction(n, d);
} |
fraction operator-(fraction f1, fraction f2)
{
int n = f1.numerator * f2.denominator -
f2.numerator * f1.denominator;
int d = f1.denominator * f2.denominator;
return fraction(n, d);
} |
fraction operator*(fraction f1, fraction f2)
{
int n = f1.numerator * f2.numerator;
int d = f1.denominator * f2.denominator;
return fraction(n, d);
} |
fraction operator/(fraction f1, fraction f2)
{
int n = f1.numerator * f2.denominator;
int d = f1.denominator * f2.numerator;
return fraction(n, d);
} |
friend functions rather than as members. So, the program must explicitly pass all arguments in parentheses and use the parameter names when accessing the objects' member variables. The advantage of constructing the new fraction at the end of the function, after it calculates the numerator and denominator, is that it allows the constructor to reduce the fraction to the lowest terms.
ostream& operator<<(ostream& out, fraction& f)
{
cout << endl << f.numerator << "/" << f.denominator << endl;
return out;
}
|
istream& operator>>(istream& in, fraction& f)
{
cin >> f.numerator;
cin >> f.denominator;
f.reduce();
return in;
} |
| (a) | (b) |
out parameter may refer to any output stream - the console, a file, etc.in may be bound to any input stream, drawing data from these sources.
int gcd(int u, int v)
{
u = (u < 0) ? -u : u;
v = (v < 0) ? -v : v;
while (u > 0)
{
if (u < v)
{
int t = u; // swap u and v
u = v;
v = t;
}
u -= v;
}
return v; // the GCD of u and v
} |
void fraction::reduce()
{
int common = gcd(numerator, denominator);
numerator /= common;
denominator /= common;
} |
| (a) | (b) |
private. See Recursion V. Iteration.private because all fraction operations reduce the objects when creating or changing them, eliminating the need for applications to perform that operation. If it becomes possible for applications to create unreduced fractions, programmers can make the function public.
#include "fraction.h" #include <iostream> using namespace std; void input(fraction& l, fraction& r); // (a) int main() { char choice; // (b) do // (c) { ... code moved to the following figure ... } while (choice != 'e' && choice != 'E'); // (d) return 0; } void input(fraction& l, fraction& r) // (e) { cout << "Left-hand fraction: numerator <space> denominator: "; cin >> l; cout << "Right-hand fraction: numerator <space> denominator: "; cin >> r; }
do
{
cout << "A\tAdd\n"; // (a)
cout << "S\tSub\n";
cout << "M\tMult\n";
cout << "D\tDiv\n";
cout << "E\tExit\n";
cout << "\nChoice?: ";
cin >> choice; // (b)
cin.ignore();
if (choice == 'E' || choice == 'e') // (c)
break;
fraction left; // (d)
fraction right;
fraction result;
input(left, right); // (e)
switch (choice) // (f)
{
case 'A':
case 'a':
result = left + right;
break;
case 'S':
case 's':
result = left - right;
break;
case 'M':
case 'm':
result = left * right;
break;
case 'D':
case 'd':
result = left / right;
break;
default:
cerr << "Unrecognized choice: " << choice << endl;
break;
}
cout << result << endl;
} while (choice != 'e' && choice != 'E');
| View | Download | Comments |
|---|---|---|
| fraction.h | fraction.h | fraction class specification illustrating operators implemented with the friend keyword |
| fraction.cpp | fraction.cpp | The fraction functions. The operator function definitions do not include the "friend" keyword |
| calc.cpp | calc.cpp | A fraction calculator using the fraction class |