includes range checking, program terminates for out-of-bound subscripts
This header file is similar in format to the Rational class examples.
The preprocessor statements and the using statement at the beginning
of the .h file are similar (except a different identifier, ARRAY_H,
to match the filename is used):
#ifndef ARRAY_H
#define ARRAY_H
#include < iostream >
using namespace std;
Consider the class definition. The private members:
int* arrayPtr;
points to the first element of an array,
int size;
is the size of the array, and
static int arrayCount;
is the number of Arrays instantiated.
Static members
The arrayCount member is static .
Typically when you instantiate an object, each object owns every member.
For example, if you have five Array objects, each has a size data
member, for a total of five. Static members are different in that they
are associated with the "class" of objects, not individual objects.
Each "class" of objects owns one static member.
The static member, arrayCount, will be used to count how many Array
objects have been instantiated, i.e., how many Array objects have been declared.
You can probably guess that any constructor will increase this count by one
since a constructor gets called every time an Array object is instantiated.
The two friend functions are identical to the
Rational class friend functions
except for the Array type:
friend ostream& operator<<(ostream &, const Array &);
friend istream& operator>>(istream &, Array &);
Notice that the constructor has a default value on its one parameter.
The constructor's parameter will be the size of the array
(the value 10 was assigned arbitrarily):
Array(int = 10);
Copy constructor and destructor
The next two functions are the copy constructor and destructor.
Whenever your object has dynamic memory associated with it,
you will need to write these.
Array(const Array &);
~Array();
Copy constructors are written to make an exact duplicate of another object.
All copy constructors will look similar in format to this one.
They are still a constructor, constructing a brand new object
(so no return type). The parameter will always be an object of the
same type as the class; it's the object that is being duplicated.
The destructor is written to deallocate any memory that was
dynamically allocated associated with the object. Typically every
class that has a pointer as a data member has a constructor
that will allocate memory for that pointer and a destructor
that will deallocate (or delete) that memory. If you don't
deallocate the memory, then a memory leak occurs.
If this memory is not deallocated, then it can never be used by you again.
If you consistently allocate memory, but don't deallocate it,
you will run out of memory. Very bad!
Member functions - old stuff
int getSize() const;
bool operator==(const Array &) const;
bool operator!=(const Array &) const;
Nothing new here. The getSize() returns the size of the array.
The overloaded operator== and operator!=
are similar to
operator+ of the Rational class.
Member functions - operator=, operator[], getArrayCount
const Array& operator=(const Array &);
int& operator[](int);
static int getArrayCount();
The overloaded operator= now has to be written because when you have
dynamic memory, the default operator= (which does a memberwise copy
of data and functions) isn't sufficient. New memory needs to be allocated.
Remember this is called when you do something like   a = b;  
The parameter is always an object of the type of the class since you're
copying its values (the righthand side of the assignment) into the
current object (the lefthand side of the assignment). This is similar
in task to the copy constructor except with the copy constructor,
you're creating a brand new object. The operator= is replacing an
existing object with a different one.
Because you're simply replacing an existing object with a different one,
the return type can be a reference, const Array&. You may as well
return the address (for efficiency) instead of making a copy of
the whole thing. This is similar to using const Array& as a parameter.
You pass the address of the thing instead of making a copy of it.
The function operator[] is actually called when you use [] on an
Array object. When you use [] with an Array object, you do it
because you're trying to simulate a regular old int array element.
To the user of the class, this notation hides that it's a
user-defined class. The return type is int& because you will use
it in something like   obj[i] = 5;  
Again, the lefthand side is getting changed (the return type),
so it has to be a reference. The details of how this works
are discussed when the .cpp file is discussed.
the getArrayCount(); is static because it returns the number
of arrays instantiated, returns the value of the static data member,
arrayCount. If you only access other static members, then
you make the function static. Having only one of them, that all
objects can use, is sufficient. Each object doesn't need their own.