Classes Inheritance

An Array Base Class



// arraydb.h -- define array class

#ifndef _ARRAYDB_H_
#define _ARRAYDB_H_
#include <iostream.h>

class ArrayDb
{
private:
	unsigned int size;			// number of array elements
protected:
	double * arr;                       // address of first element
public:
	ArrayDb();                          // default constructor
	// create an ArrayDb of n elements, set each to val
	ArrayDb(unsigned int n, double val = 0.0);
	// create an ArrayDb of n elements, initialize to array pn
	ArrayDb(const double * pn, unsigned int n);
	ArrayDb(const ArrayDb & a);         // copy constructor
	~ArrayDb();                         // destructor
	unsigned int arsize() const {return size;}   // returns array size
// overloaded operators
	double & operator[](int i);			// array indexing
	const double & operator[](int i) const;	// array indexing (no =)
	ArrayDb & operator=(const ArrayDb & a);
	friend ostream & operator<<(ostream & os, const ArrayDb & a);
};

#endif



// arraydb.cpp -- ArrayDb class methods

#include <iostream.h>
#include <stdlib.h>   // exit() prototype
#include "arraydb.h"

// default constructor -- no arguments
ArrayDb::ArrayDb()
{
   arr = NULL;
   size = 0;
}

// constructs array of n elements, each set to val
ArrayDb::ArrayDb(unsigned int n, double val)
{
   arr = new double[n];
   size = n;
   for (int i = 0; i < size; i++)
       arr[i] = val;
}

// initialize ArrayDb object to a non-class array
ArrayDb::ArrayDb(const double *pn, unsigned int n)
{
   arr = new double[n];
   size = n;
   for (int i = 0; i < size; i++)
       arr[i] = pn[i];
}

// initialize ArrayDb object to another ArrayDb object
ArrayDb::ArrayDb(const ArrayDb & a)
{
   size = a.size;
   arr = new double[size];
   for (int i = 0; i < size; i++)
       arr[i] = a.arr[i];
}

ArrayDb::~ArrayDb()
{
   delete [] arr;
}

// let user access elements by index (assignment allowed)
double & ArrayDb::operator[](int i)
{
	// check index before continuing
   if (i < 0 || i >= size)
   {
	   cerr << "Error in array limits: "
			<< i << " is a bad index\n";
	   exit(1);
   }
   return arr[i];
}

// let user access elements by index (assignment disallowed)
const double & ArrayDb::operator[](int i) const
{
	// check index before continuing
   if (i < 0 || i >= size)
   {
	   cerr << "Error in array limits: "
			<< i << " is a bad index\n";
	   exit(1);
   }
   return arr[i];
}

// define class assignment
ArrayDb & ArrayDb::operator=(const ArrayDb & a)
{
   if (this == &a)      // if object assigned to self,
		return *this;	// don't change anything
   delete arr;
   size = a.size;
   arr = new double[size];
   for (int i = 0; i < size; i++)
       arr[i] = a.arr[i];
   return *this;
}

// quick output, 5 values to a line
ostream & operator<<(ostream & os, const ArrayDb & a)
{
   for (int i = 0; i < a.size; i++)
   {
       os << a.arr[i] << " ";
       if (i % 5 == 4)
           os << "\n";
   }
   if (i % 5 != 0)
       os << "\n";
   return os;
}



// tinsel.cpp -- use the ArrayDb class

// compile with arraydb.cpp
#include <iostream.h>
#include "arraydb.h"
void display(ArrayDb & ar);
int main(void)
{
	cout << "Enter number of regions: ";
	unsigned int regions;  // read number of regions
	cin >> regions;

	ArrayDb tons(regions);  // create an "array" of that size
	cout << "Enter the regional tinsel sales in tons:\n";
	for (int i = 0; i < regions; i++)
	{
		 cout << "Region " << (i+ 1) << ": ";
		 cin >> tons[i];        // use array notation
	}

	ArrayDb dup;	// default object
	dup = tons;	// array assignment
	cout << "Here's the original data:\n" << tons;
	cout << "Here's the copy:\n";
	display(dup);	// pass array without passing size

	double wts[5] = {155.2, 189.6, 174.3, 256.9, 203.5};
	ArrayDb bod(wts, 5);	// initialize an ArrayDb to an array
	cout << "Here are the weights of the Board of Directors:\n"
		<< bod;

	// try to exceed array limit
	cout << "Index: value\n";
	for (i = 0; i <= regions; i++)
	{
		cout.width(5);
		cout << i << ": " << tons[i] << "\n";
	}

	return 0;
}

void display(ArrayDb & ar)
{
	cout << "copy!\n";
	cout << ar;
	cout << "copy!\n";
}


Inheritance - An Is-a Relationship



// aritharr.h -- derived array class with more arithmetic

#ifndef _ARITHARR_H_
#define _ARITHARR_H_

#include "arraydb.h"

class ArithArr : public ArrayDb  // derived from ArrayDb class
{
private:
	// no new data members
public:
// base class constructors not inherited,
// need ArrithArr constructors
	ArithArr(){}
	ArithArr(unsigned int n, double val = 0.0)
				: ArrayDb(n, val) {}
	ArithArr(const double *pn, unsigned int n)
				: ArrayDb(pn, n) {}
	ArithArr(const ArithArr & aa) : ArrayDb(aa) {}
	ArithArr(const ArrayDb & ad) : ArrayDb(ad) {}

// destructor ArrrayDb part is inherited, but you can define a new one
	~ArithArr() {}

// new methods
	double sum() const;
	double average() const;
// overloaded operators
	ArithArr operator+(const ArithArr & a) const;
	ArithArr operator-(const ArithArr & a) const;
	ArithArr operator-() const;
	ArithArr operator*(const ArithArr & a) const;
	ArithArr operator*(double d) const;
	friend ArithArr operator*(double d, const ArithArr & a)
};

#endif



// aritharr.cpp -- ArithArr class methods

#include <iostream.h>
#include <stdlib.h>           // exit() prototype
#include "aritharr.h"


// new methods
double ArithArr::sum() const
{
   unsigned int size = arsize();	// access base via method
   double total = 0.0;
   for (int i = 0; i < size; i++)
	   total += arr[i];			// access base directly
   return total;
}

double ArithArr::average() const
{
   unsigned int size = arsize();
   if (size < 1)
   {
       cout << "Computing an average requires at least "
               "one array element -- bye.\n";
       exit(1);
   }
   return sum() / size;
}

// overloaded operators
ArithArr ArithArr::operator+(const ArithArr & a) cons
{
	unsigned int size = arsize();
	unsigned int asize = a.arsize();
	if (size != asize)
	{
		cerr << "+ not defined for arrays of unequal size\n";
		exit(1);
	}
	ArithArr total(size);
	for (int i = 0; i < size; i++)
		total[i] = arr[i] + a.arr[i];
	return total;
}

ArithArr ArithArr::operator-(const ArithArr & a) const
{
	unsigned int size = arsize();
	unsigned int asize = a.arsize()
	if (size != asize)
	{
		cerr << "- not defined for arrays of unequal size\n";
		exit(1);
	}
	ArithArr diff(size);
	for (int i = 0; i < size; i++)
		diff[i] = arr[i] - a.arr[i];
	return diff;
}

ArithArr ArithArr::operator-() const
{
	unsigned int size = arsize();
	ArithArr neg(size);
	for (int i = 0; i < size; i++)
		neg[i] = -arr[i];
		return neg;
}


ArithArr ArithArr::operator*(const ArithArr & a) const
{
	unsigned int size = arsize();
	unsigned int asize = a.arsize();
	if (size != asize)
   {
       cout << "Array multiplication error: arrays must "
               "be of same size. Bye.\n";
       exit(1);
   }
   ArithArr product(size);
   for (int i = 0; i < size; i++
	   product[i] = arr[i] * a.arr[i];
   return product;
}

ArithArr ArithArr::operator*(double d) const
{
	unsigned int size = arsize();
	ArithArr temp(size);
	for (int i = 0; i < size; i++
		temp[i] = arr[i]*d
	return temp;
}


ArithArr operator*(double d, const ArithArr & a)
{
	return a*d;
}



// derived.cpp -- use a derived class

// compile with aritharr.cpp and arraydb.cpp
#include <iostream.h>
#include <stdlib.h>              // exit() prototype
#include "aritharr.h"

void show(const ArrayDb & ar, int index);

const int things = 4;
double price[things] = { 9.95, 28.55, 8.99, 1.50 };
int main(void)
{
	ArithArr prices1(price, things);
	ArithArr prices2(prices1);
	prices2 = 1.05 * prices1;  // multiplication, assignment
	ArithArr sales1(things);
	ArithArr sales2(things);
	cout << "Enter sales for first half:\n"
	<< "disks   mitts  tapes   cards\n";
	for (int i = 0; i < things; i++)
		cin >> sales1[i];
	cout << "Enter sales for second half:\n"
	<< "disks   mitts  tapes   cards\n";
	for (i = 0; i < things; i++)
		cin >> sales2[i];
	ArithArr allsales = sales1 + sales2;
	cout << "Total sales:\n" << allsales;
	ArithArr gross = sales1 * prices1 + sales2 * prices2;
	cout.precision(2);	// 2 places to right of decimal
	cout.setf(ios::showpoint);	// show trailing 0s
	cout.setf(ios::fixed, ios::floatfield); // fixed point
	cout << "Gross take in dollars per item:\n" << gross;
	cout << "Let's see that with a $:\n";
	for (i = 0; i < things; i++)
		show(gross, i); 		// ArrayDb reference
	cout << "Total gross: $" << gross.sum() << "\n";

	return 0;
}

void show(const ArrayDb & ar, int index)
{
	cout << index << ": $" << ar[index] << "\n";
}



// limarr.h -- LimitArr class


#ifndef _LIMARR_H_
#define _LIMARR_H_

#include "arraydb.h"

class LimitArr : public ArrayDb
{
protected:
   unsigned int low_bnd;      // new data member
   void ok(int i) const;      // handle bounds checking
public:
// constructors
   LimitArr();
   LimitArr(unsigned int n, double val = 0.0);
   LimitArr(unsigned int n, int lb, double val = 0.0);
   LimitArr(const double * pn, unsigned int n);
   LimitArr(const LimitArr & a);
   LimitArr(const ArrayDb & a);
// new methods
   void new_lb(int lb) {low_bnd = lb; }  // reset lower bound
   int lbound() {return low_bnd;}   // return lower bound
   int ubound() {return low_bnd + arsize() -1;} // return upper bound
// redefined operators
   double & operator[](int i);
   const double & operator[](int i) const;
};

#endif


// limarr.cpp -- LimitArr methods

#include "limarr.h"
#include <iostream.h>
#include <stdlib.h>

// private method
   // lower bound for array index is now low_bnd, and 
   // upper bound is now low_bnd + size - 1
void LimitArr::ok(int i) const  // variable lower bound
{
	unsigned long size = arsize();
	if (i < low_bnd)
	{
       cout << "Error in array limits:\n"
            << "index " << i << " less than "
            << low_bnd <<  "\n";
       exit(2);
	}
	else if (i >= size + low_bnd)
	{
       cout << "Error in array limits:\n"
            << "index " << i << " greater than "
            << size + low_bnd - 1 << "\n";
       exit(3);
	}
}

// constructors -- initialize the new data member
LimitArr::LimitArr() : ArrayDb()
{
   low_bnd = 0;   // default sets starting subscript to 0
}

LimitArr::LimitArr(unsigned int n, double val) : ArrayDb(n, val)
{
   low_bnd = 0;   // default value
}

LimitArr::LimitArr(unsigned int n, int lb, double val)
   : ArrayDb(n, val)
{
   low_bnd = lb;  // set starting subscript explicitly
}

LimitArr::LimitArr(const double * pn, unsigned int n)
   : ArrayDb(pn, n)
{
   low_bnd = 0;
}

LimitArr::LimitArr(const LimitArr & a) : ArrayDb(a)
{
    low_bnd = a.low_bnd;
}

LimitArr::LimitArr(const ArrayDb & a) : ArrayDb(a)
{
   low_bnd = 0;
}

// redefined operators
double & LimitArr::operator[](int i)
{
   ok(i);
   return arr[i - low_bnd];
}

const double & LimitArr::operator[](int i) const
{
   ok(i);
   return arr[i - low_bnd];
}



// use_lim.cpp -- use the LimitArr class

// Compile with limarr.cpp and arraydb.cpp
#include <iostream.h>
#include "limarr.h"

void show(const ArrayDb & ar, int index);
const int YEAR = 1977;
const int YEARS = 5;
int main(void)
{
   LimitArr vintages(YEARS, YEAR);
   cout << "Enter bids for the following vintages of "
           "Chateau Spiff:\n";
   for (int year = YEAR; year < YEAR + YEARS; year++)
   {
       cout << "Year " << year << ": $";
       cin >> vintages[year];
   }
   cout.precision(2);
   cout.setf(ios::showpoint);
   cout.setf(ios::fixed, ios::floatfield);
   cout << "Recapitulating, here are the bids in dollars:\n";
   cout << vintages;
   cout << vintages[1978] << "\n";
   cout << "The following bids were accepted:\n";
   LimitArr copy;
   copy = vintages;
   int bid1 = 1978;
   int bid2 = 1980;
   cout << bid1 << ": $" << copy[bid1] << "\n";
   show(copy, bid2);
   return 0;
}

void show(const ArrayDb & ar, int index)
{
	cout << index << ": $" << ar[index] << "\n";
}



Virtual Member Functions



// arraydb.h -- revised array class, making [] virtual

#ifndef _ARRAYDB_H_
#define _ARRAYDB_H_
#include <iostream.h>

class ArrayDb
{
private:
	unsigned int size;			// number of array elements
protected:
	double * arr;                       // address of first element
public:
	ArrayDb();                          // default constructor
	// create an ArrayDb of n elements, set each to val
	ArrayDb(unsigned int n, double val = 0.0);
	// create an ArrayDb of n elements, initialize to array pn
	ArrayDb(const double * pn, unsigned int n);
	ArrayDb(const ArrayDb & a);         // copy constructor
	virtual ~ArrayDb();  // destructor
	unsigned int arsize() const {return size;}   // returns array size
// overloaded operators -- note use of keyword virtual
	virtual double & operator[](int i);	// array indexing
	virtual const double & operator[](int i) const;// array indexing (no =)
	ArrayDb & operator=(const ArrayDb & a);
	friend ostream & operator<<(ostream & os, const ArrayDb & a);
};

#endif