|
The somethings are what we call coefficients.
We would like both ints and strings to serve as coefficients. That is we would like to have polynomials that look like 2x2 + 3x + 4 and polynomials that look like ax2 + bx + c.
Also, we should be able to add polynomials with + and get something that looks reasonable.
And by default, a polynomial should look like 0x2 + 0x + 0 no matter what kind of coefficients (int or string) it has.
I make a poly template class. The default constructor sets the coefficients to zero. The trouble is that zero for an int is 0, but zero for a string is "0".
One way to handle this is as follows:
Wrappers are a pretty common thing to do. If you learn about Windows programming you will find that Microsoft created its own wrappers for the basic C++ data types. If you learn Java you will find that Java has its own wrapper classes for its basic data types.
A static constant is a constant that belongs to the class and not objects of the class.
The ZERO constant in the Int class is set up by the line static int ZERO; in the public section of the class. The ZERO constant in the String class is set up by the line static string ZERO; int the public section of the String class.
The static ZERO constant in the Int class is set by the line int Int::ZERO = 0; and the static ZERO constant in the String class is set by the line string String::ZERO = ""; in the coefficients.cpp file.
The ZERO constants I define in the Int and String classes are invoked by the statements Int.ZERO and String.ZERO in the places they are used.
The file polyMain.cpp:
#include <iostream>
#include "coefficients.h"
#include "poly.h"
using namespace std;
int main ()
{
//Set up three Int type polynomials.
poly <Int> one, two (1,2,3), three (3,4,6);
cout << one << endl;
cout << two << endl;
cout << three << endl;
cout << two + three << endl;
//Set up three String type polynomials.
poly <String> four ("a","b","c"), five ("A","B","C"), six;
cout << four << endl;
cout << five << endl;
cout << four + five << endl;
cout << six << endl;
return 0;
}
The file coefficients.h:
#ifndef COEFFICIENT_H
#define COEFFICIENT_H
#include <iostream>
#include <string>
using namespace std;
class Int
{
friend ostream& operator<< (ostream&, Int& anInt);
friend Int operator+ (Int& one, Int& two);
public:
Int (int n = 0); //If no arguments then n is set to 0
Int (Int&);
Int& operator= (int);
static int ZERO; //ZERO belongs to the class not to objects
private:
int val;
};
class String
{
friend ostream& operator<< (ostream&, String&);
friend String operator+ (String& one&, String& two);
public:
String (string n = ""); //If no arguments then n gets ""
String (String&);
String (char []); //For handling C strings
String& operator= (String&);
static string ZERO; //ZERO belongs to the class not to objects
private:
string val;
};
#endif
The file coefficients.cpp:
//First the particulars for the Int class
//Initialization of the static constant ZERO
int Int::ZERO = 0;
Int::Int (int n)
{
val = n;
}
Int::Int (Int& aInt)
{
val = aInt.val;
}
Int& Int::operator= (Int& aInt)
{
val = aInt.val;
return *this;
}
ostream& operator<< (ostream& out, Int& aInt)
{
out << aInt.val;
return out;
}
Int operator+ (Int& one, Int& two)
{
Int temp (one.val + two.val);
return temp;
}
//Now the particulars for the String class
//Initialization of the static constant ZERO
string String::ZERO = "0";
String::String (string& astring)
{
val = aString;
}
String::String (String& aString)
{
val = aString.val;
}
String::String (char array [])
{
val = array;
}
String& operator= (String& aString)
{
val = aString.val;
return *this;
}
ostream& operator<< (ostream& out, String& aString)
{
out << aString.val;
return out;
}
String operator+ (String& one, String& two)
{
String temp (one.val + two.val);
return temp;
}
Finally, the file poly.h that defines the polynomial template class. Notice that the class definition and the functions all go together in one file when you make a template.
You will notice that the operator<< and operator+ function are not friends of the class for a change. It seems that friends can be problematic in templates. To get around this problem I provide public functions to access the data of the class.
#ifndef POLY_H
#define POLY_H
template<class T>
class poly
{
public:
poly (); //Default gives 0 coefficients
poly (const T&, const T&, const T&);
poly (poly<T>&);
poly<T>& operator= (poly<T>&);
T getOne (); //Functions needed to make operator<< and operator+ work
T getTwo ();
T getThree ();
private:
T one;
T two;
T three;
};
template<class T>
poly<T>::poly ()
{
one = T.ZERO; //Calls the ZERO constant of the T class: Int or String
two = T.ZERO;
three = T.ZERO;
}
template<class T>
poly<T>::poly (const T& A, const T& B, const T& C)
{
one = A;
two = B;
three = C;
}
template<class T>
poly<T>::poly (poly<T>& aPoly)
{
one = aPoly.one;
two = aPoly.two;
three = aPoly.three;
}
template<class T>
poly<T>& poly<T>::operator= (poly<T>& it)
{
one = it.one;
two = it.two;
three = it.three;
return *this;
}
template<class T>
T poly<T>::getOne ()
{
return one;
}
template<class T>
T poly<T>::getTwo ()
{
return two;
}
template<class T>
T poly<T>::getThree ()
{
return three;
}
template<class T>
ostream& operator<< (ostream& out, poly<T>& it)
{
T one = it.getOne ();
T two = it.getTwo ();
T three = it.getThree ();
out << one << "x^2 + " << two << "x + " << three << endl;
return out;
}
template<class T>
poly<T> operator+ (poly<T>& first, poly<T>& second)
{
T newOne = first.getOne () + second.getOne ();
T newTwo = first.getTwo () + second.getTwo ();
T newThree = first.getThree () + second.getThree ();
poly<T> temp (newOne, newTwo, newThree);
return temp;
}
#endif