The previous section developed a solution to the pouring puzzle using pictures, diagrams, and pseudocode. The current section implements the solution, transforming it into a functional program consisting of three files. The first two files, Glass.h and Glass.cpp, implement a Glass class forming a supplier, while the third, game.cpp, represents the client that uses it. Although this organization and most of the programming features are familiar, the program authentically demonstrates several object-oriented programming features.
The first feature is a static class variable named pours that counts the number of pouring operations that the player makes to solve the puzzle. A static variable is the preferred way to maintain the count and the only way that avoids a global variable. The Glass class makes the variable private, preventing clients from "cheating" by altering the stored value. However, the client may need to retrieve the count, so the second demonstrated feature is a static getter function. The definition of the getter function is unremarkable, but the syntax for calling it is notable.
The pour function demonstrates the remaining features: the effect of using an object as an implicit this argument versus as an explicit one, and a binary function that modifies both arguments (requiring the program to pass both using an INOUT technique). The function arbitrarily designates the this argument as the destination of the poured water and the explicit argument as the source. Given two Glass objects, g1 and g2, and the function call g1.pour(g2), pours or transfers water from g2 to g1. g1 is always passed to the function by pointer, but programmers can choose to pass g2 by pointer or by reference. The logic is the same in both cases, and the example presents both versions in parallel.
#include <iostream>
using namespace std;
class Glass
{
private:
static int pours; // (a)
int volume; // (b)
int amount; // (c)
public:
Glass(int a_volume, int a_amount) : volume(a_volume), amount(a_amount) {}
int getVolume() { return volume; }
int getAmount() { return amount; }
void display() { cout << amount << " / " << volume << endl; }
static int getPours() { return pours; }
void pour(Glass& source); // (d)
//void pour(Glass* source); // (e)
};
| Pass By Reference | Pass By Pointer | |
|---|---|---|
#include "Glass.h" #include <algorithm> using namespace std; int Glass::pours = 0; void Glass::pour(Glass& source) { pours++; int space = volume - amount; int transfer = min(space, source.amount); amount += transfer; source.amount -= transfer; } |
(a) (b) (c) (d) (e) (f) |
#include "Glass.h" #include <algorithm> using namespace std; int Glass::pours = 0; void Glass::pour(Glass* source) { pours++; int space = volume - amount; int transfer = min(space, source->amount); amount += transfer; source->amount -= transfer; } |
int transfer =
(space < source.amount) ? space : source.amount; |
(g) |
int transfer =
(space < source->amount) ? space : source->amount; |
if (space < source.amount) { source.amount -= space; amount = volume; // amount += space; } else { amount += source.amount; source.amount = 0; } |
(h) |
if (space < source->amount) { source->amount -= space; amount = volume; // amount += space; } else { amount += source->amount; source->amount = 0; } |
#include <iostream>
#include "Glass.h"
using namespace std;
int main()
{
Glass glasses[3] { Glass(3,0), Glass(5,0), Glass(8,8) }; // (a) - Reference
//Glass* glasses[] { new Glass(3,0), new Glass(5,0), new Glass(8,8) }; // - Pointer
while (glasses[1].getAmount() != 4 && glasses[2].getAmount() != 4) // (b)
//while (glasses[1]->getAmount() != 4 && glasses[2]->getAmount() != 4)
{
for (int i = 0; i < 3; i++) // (c)
{
cout << "Glass " << i+1 << ": ";
glasses[i].display();
//glasses[i]->display();
}
int destination;
cout << "Pour TO glass: <1, 2, or 3; or enter 4 to quit>: "; // (d)
cin >> destination;
if (destination == 4)
exit(0);
int source;
cout << "Pour FROM glass: <1, 2, or 3; or enter 4 to quit>: "; // (e)
cin >> source;
if (source == 4)
exit(0);
if (source > 0 && source <= 3 && destination > 0 && destination <= 3) // (f)
glasses[destination - 1].pour(glasses[source - 1]); // (g)
//glasses[destination - 1]->pour(glasses[source - 1]);
else
cout << "0 < destination <= 3 AND 0 < source <= 3" << endl;
}
cout << "\n\nYou solved the puzzle in " << Glass::getPours() << " pours" << endl; // (h)
for (int i = 0; i < 3; i++) // (i)
glasses[i].display();
//glasses[i]->display();
return 0;
}
static functions to classes rather than objects.| View | Download | Comments |
|---|---|---|
| Glass.h | Glass.h | Pass by reference version |
| fraction.cpp | fraction.cpp | |
| calc.cpp | calc.cpp | |
| Glass.h | Glass.h | Pass by pointer version |
| fraction.cpp | fraction.cpp | |
| game.cpp | game.cpp |