Overview
This project is the first of two projects that compare two major C++ programming techniques: OO (using inheritance) and templates (generic programming).
We know how to create and sort arrays and vectors of ints, and thus other primitives. A collection of any type that has an overloaded < operator, essentially, can be sorted. Now we want to do the same with vectors of wrapper objects using the first of the two approaches mentioned above (OO).
For our wrapper objects to be comparable, we will mimic Java and write a compare member function. obj1.compare(obj2) will return -1 if obj1 < obj2, 0 if obj1 == obj2, and 1 if obj1 > obj2. Focusing on abstract types from Module 9, we also want to be work with vectors of any type that implements an interface that we create called IComparable. The problem we are trying to solve in this project and the next one is the same: how to create a framework by which several types of wrapper objects, each wrapping a different primitive (or even a simple object) type, can be “forced” to behave according to certain rules.
You will then create three derived classes, Integer, Double, and Character that act as wrappers for int, double, and char primitives, respectively. You will also provide an external overloaded << operator for IComparable objects, for which you need to decide whether it can or cannot be implemented solely as part of the IComparable interface. Whatever you decide is part of the IComparable interface will be completely defined in IComparable.h.
Place the declaration and implementation for the three concrete classes in a file called Wrappers.h. No member function should exceed a few lines, which makes the .h file layout practical.
In the concrete classes Integer, Double, and Character, we have a few other concerns, such as how to construct stack-based objects of this type, copy semantics, etc. Since our wrappers are value-based, we can avoid dealing with move semantics for this project, so you do not have to write move constructors or move assignment functions.
A rough outline and partial implementation of the Integer class is given below as a starting point. The Character and Double classes would be very similar.
Project-specific Requirements
R1. Provide full implementations for the derived classes Integer, Double, and Character, where Integer wraps a primitive int, Double wraps a primitive double, and Character wraps a primitive char (NOT a char*, just a plain char). Note that the data members are not pointers, static const members, references, etc.—just simple primitive types.
R2. Define a private data member of the appropriate type called value for each of the three derived classes.
R3. Provide wrapper class implementations of the print() function for the concreate classes that will be called by the external operator<< overload.
NOTE: print () is the only required public simple accessor in the derived classes, but you may define others for debugging. For example, you might write a simple getValue() accessor in each wrapper class if you need it early on. [Think about why you cannot write getValue() in the abstract base class.]
R4. Each of the derived wrapper classes must have a single-arg constructor with a default parameter to serve as the no-arg constructor as well. For the Integer class, the default value is 0. For the Double, use 0.0, and for the Character class, use the ? character.
R5. Provide a suitable destructor for the abstract base class.
R6. Support default construction, single-arg construction, copy construction, and copy assignment of stack-based objects of type Integer, Double, and Character.
R7. Support default and single-arg construction, copy construction, and copy assignment of pointers or references to IComparables (i.e., test the polymorphic behavior of your IComparable interface and related concrete objects).
R8. Provide declarations/implementations of any and all pure virtual functions in the base class for each of the three derived classes.
R9. Use standard header guards as opposed to #pragma once directives in your IComparable.h and Wrapper.h files. Watch your #includes to make sure all of the types used in various files are visible.
R10. In general, any member function that can be implemented in the IComparable base class should be done in that class one time, as opposed to duplicating it in each of the three concrete classes. A good example is the operator< which is implemented in terms of compare().