CS 10B Programming Concepts and Methodologies 1

Project 24.2

Since you are working with code written by someone else, no documentation is required for this project.

Convert the OrderedPair class, which is provided below, into a templated class. Note that it will only work with types that have the operators + and < and << overloaded. But you should be able to try your templated class out with types string, MyString, double, FeetInches, Fraction, etc. I would encourage you to try these out.

Also, create a programmer-defined exception class named "DuplicateMemberError" and add an if statement to each of the two mutators to throw this exception if the precondition has not been met. The precondition is given as a comment in the header file. Notice that you can test your exception handling by entering the same number twice when prompted for two numbers.

Put your class in a namespace named "cs_pairs"

Finally, to show that your class will work with different types, and also to show that you know how to code a client that uses the templated class, modify the given client file so that it uses your class using int as the type parameter, and then, in the same main(), repeat the code again with a few changes necessary to make it use ordered pairs of Strings instead of ordered pairs of ints. One of the things you'll have to change is the generation of the random values for the ordered pairs. Here's what I used:

    string empty = "";
    myList2[i].setFirst(empty + char('a' + rand() % 26));
    myList2[i].setSecond(empty + char('A' + rand() % 26));

Important Submission Note

Unfortunately zyBooks doesn't seem to play well with templated classes. Before submitting, you need to do the following:

  • In main.cpp you need

    #include "OrderedPair.h"
    #include "OrderedPair.cpp"
    
  • In OrderedPair.cpp you need

    #include "OrderedPair.h"
    
  • No #includes in OrderedPair.h (so you'll need to delete the #include at the bottom).

  • Don't forget to use #ifndef, etc. in your header file.

Here is the header file, OrderedPair.h. The syntax for declaring a constant in a class may look mysterious. To use constants in a class, we have to declare it inside the class, then assign it a value outside the class, as you'll see below. (That's actually not true for int constants -- they can be assigned inside the class -- but we want our code to be flexible enough to handle different types.)

#include <iostream>

/* precondition for setFirst and setSecond: the argument cannot be such that the values of
first and second will become equal, unless the argument is equal to DEFAULT_VALUE.
*/


namespace cs_pairs {
    class OrderedPair {
        public:
            static const int DEFAULT_VALUE;
            OrderedPair(int newFirst = DEFAULT_VALUE, int newSecond = DEFAULT_VALUE);
            void setFirst(int newFirst);
            void setSecond(int newSecond);
            int getFirst() const;
            int getSecond() const;
            OrderedPair operator+(const OrderedPair& right) const;
            bool operator<(const OrderedPair& right) const;
            void print() const;
        private:
            int first;
            int second;
    };

}


Here is the implementation file, OrderedPair.cpp

#include "OrderedPair.h"
#include <iostream>
using namespace std;

namespace cs_pairs {


    // Note: C++ requires that we initialize DEFAULT_VALUE here instead of inside the
    // class declaration.
    
    // You'll also need a template prefix before this line, just like if it was a
    // member function.
        
    const int OrderedPair::DEFAULT_VALUE = int();


    OrderedPair::OrderedPair(int newFirst, int newSecond) {
        setFirst(newFirst);
        setSecond(newSecond);
    }

    void OrderedPair::setFirst(int newFirst) {
    // if statement to throw an exception if precondition not met goes here.        
        first = newFirst;
    }

    void OrderedPair::setSecond(int newSecond) {
    // if statement to throw an exception if precondition not met goes here.    
        second = newSecond;
    }

    int OrderedPair::getFirst() const {
        return first;
    }

    int OrderedPair::getSecond() const {
        return second;
    }

    OrderedPair OrderedPair::operator+(const OrderedPair& right) const {
        return OrderedPair(first + right.first, second + right.second);
    }


    bool OrderedPair::operator<(const OrderedPair& right) const {
        return first + second < right.first + right.second;
    }


    void OrderedPair::print() const {
        cout << "(" << first << ", " << second << ")";
    }
}

Here is the client file.

#include <iostream>
#include <ctime>
#include <cstdlib>
#include "OrderedPair.h"
using namespace std;
using namespace cs_pairs;





int main() {
    int num1, num2;
    OrderedPair myList[10];
    
    srand(static_cast<unsigned>(time(0)));
    cout << "default value: ";
    myList[0].print();
    cout << endl;
    
    for (int i = 0; i < 10; i++) {
        myList[i].setFirst(rand() % 50);
        myList[i].setSecond(rand() % 50 + 50);
    }
    
    myList[2] = myList[0] + myList[1];
    
    if (myList[0] < myList[1]) {
        myList[0].print();
        cout << " is less than ";
        myList[1].print(); 
        cout << endl;
    }
    
    for (int i = 0; i < 10; i++) {
        myList[i].print();
        cout << endl;
    }
    
    cout << "Enter two numbers to use in an OrderedPair.  Make sure they are different numbers: ";
    cin >> num1 >> num2;
    OrderedPair x;
    
    /* use this before you've implemented the exception handling in the class:
    */
    
    x.setFirst(num1);
    x.setSecond(num2);
    
    /* use this after you've implemented the exception handling in the class:
    try {
        x.setFirst(num1);
        x.setSecond(num2);
    } catch (OrderedPair::DuplicateMemberError e) {
        cout << "Error, you attempted to set both members of the OrderedPair to the same number." 
             << endl;
        x.setFirst(OrderedPair::DEFAULT_VALUE);
        x.setSecond(OrderedPair::DEFAULT_VALUE);        
    }
    */
    
    cout << "The resulting OrderedPair: ";
    x.print();
    cout << endl;
}