We want to implement array class with the following specifications:
- range checking.
- array assignment.
- arrays that know their size.
- compare arrays using '==' and '!=' operators.
In the next example we will implement a simple class for integers is called Array, it has the previous specifications, and it has the following structure:
class Array {
friend ostream &operator<<( ostream &, const Array & );
friend istream &operator>>( istream &, Array & );
public:
Array( int = 10 ); // default constructor
Array( const Array & ); // copy constructor
~Array(); // destructor
int getSize() const; // return size
const Array &operator=( const Array & ); // assign arrays
bool operator==( const Array & ) const; // compare equal
// Determine if two arrays are not equal and
// return true, otherwise returnfalse (uses operator==).
bool operator!=( const Array &right ) const;
int &operator[]( int ); // subscript operator
const int &operator[]( int ) const; // subscript operator
static int getArrayCount(); // Return count of
// arrays instantiated.
private:
int size; // size of the array
int *ptr; // pointer to first element of array
static int arrayCount; // # of Arrays instantiated
};
Functions Implementation:
1- Default Constructor:
// Default constructor for class Array (default size 10)
Array::Array( int arraySize )
{
size = (arraySize > 0 ?arraySize : 10 );
ptr = new int[ size ]; // create space for array
assert(ptr != 0 ); // terminate if memory not allocated
++arrayCount; // count one more object
for ( int i = 0; i < size; i++ )
ptr[ i ] = 0; // initialize array
}
2- Copy Constructor:
// Copy constructor for class Array
// must receive a reference to prevent infinite recursion
Array::Array( constArray &init ) : size( init.size )
{
ptr = new int[ size ]; // create space for array
assert(ptr != 0 ); // terminate if memory not allocated
++arrayCount; // count one more object
for ( int i = 0; i < size; i++ )
ptr[ i ] = init.ptr[ i ]; // copy init into object
}
3- Destructor:
// Destructor for class Array
Array::~Array()
{
delete [] ptr; // reclaim space for array
--arrayCount; // one fewer object
}
4- Get Size:
// Get the size of the array
int Array::getSize() const
{
return size;
}
5- Overloaded Assignment Operator:
// const return avoids: ( a1 = a2 ) = a3
const Array &Array::operator=( const Array &right )
{
if ( &right != this )
{ // check for self-assignment
// for arrays of different sizes, deallocateoriginal
// left side array, then allocate new left side array.
if ( size != right.size )
{
delete []ptr; // reclaim space
size = right.size; // resize this object
ptr = newint[ size ]; // create space for array copy
assert( ptr != 0 ); // terminate if not allocated
}
for ( int i = 0; i < size; i++ )
ptr[ i ] = right.ptr[ i ]; // copy array into object
}
return *this; // enables x = y = z;
}
6- Determine If Two Arrays are Equal:
// Determine if two arrays are equal and
// return true, otherwise return false.
bool Array::operator==( const Array &right ) const
{
if ( size != right.size )
return false; // arrays of different sizes
for ( int i = 0; i < size; i++ )
if ( ptr[ i ] != right.ptr[ i ] )
return false; // arrays are not equal
return true; // arrays are equal
}
7- Overloaded Subscript Operator:
// Overloaded subscript operator for non-const Arrays
// reference return creates an lvalue
int &Array::operator[]( int subscript )
{
// check for subscript out of range error
assert( 0 <= subscript && subscript < size );
return ptr[ subscript ]; // reference return
}
8- Overloaded Subscript Operator for Const Arrays:
<code></code>
// Overloaded subscript operator for const Arrays
// const reference return creates an rvalue
const int &Array::operator[]( int subscript ) const
{
// check for subscript out of range error
assert( 0 <= subscript && subscript < size );
return ptr[ subscript ]; // const reference return
}
9- Return the Number of Array Objects Instantiated:
// Return the number of Array objects instantiated
// static functions cannot be const
int Array::getArrayCount()
{
return arrayCount;
}
10- Overloaded Input Operator:
// Overloaded input operator for class Array;
// inputs values for entire array.
istream &operator>>( istream &input, Array &a )
{
for ( int i = 0; i < a.size; i++ )
input >> a.ptr[ i ];
return input; // enables cin >> x >> y;
}
11- Overloaded Output Operator:
// Overloaded output operator for class Array
ostream &operator<<( ostream &output, constArray &a )
{
int i;
for ( i = 0; i < a.size; i++ )
{
output << setw( 12 ) << a.ptr[ i ];
if ( ( i + 1 ) % 4 == 0 ) // 4 numbers per row of output
output <<endl;
}
if ( i % 4 != 0 )
output << endl;
return output; // enables cout<< x << y;
}
After we implement all functions we test them:
int main()
{
// no objects yet
cout << "# of arrays instantiated = "
<< Array::getArrayCount() << '\n';
// create two arrays andprint Array count
Array integers1( 7 ), integers2;
cout << "# of arrays instantiated = "
<< Array::getArrayCount() << "\n\n";
// print integers1 size and contents
cout << "Size of array integers1 is "
<< integers1.getSize()
<< "\nArrayafter initialization:\n"
<< integers1 << '\n';
// print integers2 size and contents
cout << "Size of array integers2 is "
<< integers2.getSize()
<< "\nArrayafter initialization:\n"
<< integers2 << '\n';
// input and print integers1 and integers2
cout << "Input 17 integers:\n";
cin >> integers1 >> integers2;
cout << "After input, the arrays contain:\n"
<< "integers1:\n" << integers1
<< "integers2:\n" << integers2 << '\n';
// use overloaded inequality (!=) operator
cout << "Evaluating: integers1 != integers2\n";
if ( integers1 != integers2 )
cout<< "They are not equal\n";
// create array integers3 using integers1 as an
// initializer; print size and contents
Array integers3( integers1 );
<< "\nSizeof array integers3 is "
<< integers3.getSize()
<< "\nArrayafter initialization:\n"
<< integers3 << '\n';
// use overloaded assignment (=) operator
cout << "Assigning integers2 to integers1:\n";
integers1 = integers2;
cout << "integers1:\n" << integers1
<< "integers2:\n" << integers2 << '\n';
// use overloaded equality (==) operator
cout << "Evaluating: integers1 == integers2\n";
if ( integers1 == integers2 )
cout<< "They are equal\n\n";
// use overloaded subscript operator to create rvalue
cout << "integers1[5] is " << integers1[ 5 ] << '\n';
// use overloaded subscript operator to create lvalue
cout << "Assigning 1000 to integers1[5]\n";
integers1[ 5 ] = 1000;
cout << "integers1:\n" << integers1 << '\n';
// attempt to use out of range subscript
cout << "Attempt to assign 1000 to integers1[15]" << endl;
integers1[ 15 ] = 1000; // ERROR: out of range
return 0;
}
The output:
# of arrays instantiated = 0
# of arrays instantiated = 2
Size of array integers1 is 7
Array after initialization:
0 0 0 0
0 0 0
Size of array integers2 is 10
Array after initialization:
0 0 0 0
0 0 0 0
0 0
Input 17 integers:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
After input, the arrays contain:
integers1:
1 2 3 4
5 6 7
integers2:
8 9 10 11
12 13 14 15
16 17
Evaluating: integers1 != integers2
They are not equal
Size of array integers3 is 7
Array after initialization:
1 2 3 4
5 6 7
Assigning integers2 to integers1:
integers1:
8 9 10 11
12 13 14 15
16 17
integers2:
8 9 10 11
12 13 14 15
16 17
Evaluating: integers1 == integers2
They are equal
integers1[5] is 13
Assigning 1000 to integers1[5]
integers1:
8 9 10 11
12 1000 14 15
16 17
Attempt to assign 1000 to integers1[15]
Assertion failed: 0
Note: You can find the full source code of this example in code.zip file.