Link to home
Start Free TrialLog in
Avatar of aditya86b
aditya86bFlag for United States of America

asked on

array class operator oveloading

How can I add three more additional operators for the following program.

// Fig. 11.8: fig11_08.cpp
// Array class test program.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
 
#include "Array.h"
 
int main()
{
   Array integers1( 7 ); // seven-element Array
   Array integers2; // 10-element Array by default
 
   // print integers1 size and contents
   cout << "Size of Array integers1 is " 
      << integers1.getSize()
      << "\nArray after initialization:\n" << integers1;
 
   // print integers2 size and contents
   cout << "\nSize of Array integers2 is " 
      << integers2.getSize()
      << "\nArray after initialization:\n" << integers2;
 
   // input and print integers1 and integers2
   cout << "\nEnter 17 integers:" << endl;
   cin >> integers1 >> integers2;
 
   cout << "\nAfter input, the Arrays contain:\n"
      << "integers1:\n" << integers1
      << "integers2:\n" << integers2;
 
   // use overloaded inequality (!=) operator
   cout << "\nEvaluating: integers1 != integers2" << endl;
 
   if ( integers1 != integers2 )
      cout << "integers1 and integers2 are not equal" << endl;
 
   // create Array integers3 using integers1 as an
   // initializer; print size and contents
   
   
   
   
   
   Array integers3( integers1 ); // invokes copy constructor
 
   cout << "\nSize of Array integers3 is "
      << integers3.getSize()
      << "\nArray after initialization:\n" << integers3;
 
   // use overloaded assignment (=) operator
   cout << "\nAssigning integers2 to integers1:" << endl;
   integers1 = integers2; // note target Array is smaller
 
   cout << "integers1:\n" << integers1
      << "integers2:\n" << integers2;
 
   // use overloaded equality (==) operator
   cout << "\nEvaluating: integers1 == integers2" << endl;
 
   if ( integers1 == integers2 )
      cout << "integers1 and integers2 are equal" << endl;
 
   // use overloaded subscript operator to create rvalue
   cout << "\nintegers1[5] is " << integers1[ 5 ];
 
   // use overloaded subscript operator to create lvalue
   cout << "\n\nAssigning 1000 to integers1[5]" << endl;
   integers1[ 5 ] = 1000;
   cout << "integers1:\n" << integers1;
 
   // attempt to use out-of-range subscript
   cout << "\nAttempt to assign 1000 to integers1[15]" << endl;
   integers1[ 15 ] = 1000; // ERROR: out of range
   return 0;
} // end main
 
/**************************************************************************
 * (C) Copyright 1992-2005 by Deitel & Associates, Inc. and               *
 * Pearson Education, Inc. All Rights Reserved.                           *
 *                                                                        *
 * DISCLAIMER: The authors and publisher of this book have used their     *
 * best efforts in preparing the book. These efforts include the          *
 * development, research, and testing of the theories and programs        *
 * to determine their effectiveness. The authors and publisher make       *
 * no warranty of any kind, expressed or implied, with regard to these    *
 * programs or to the documentation contained in these books. The authors *
 * and publisher shall not be liable in any event for incidental or       *
 * consequential damages in connection with, or arising out of, the       *
 * furnishing, performance, or use of these programs.                     *
 **************************************************************************/
 
 
 
// Fig 11.7: Array.cpp
// Member-function definitions for class Array
#include <iostream>
using std::cerr;
using std::cout;
using std::cin;
using std::endl;
 
#include <iomanip>
using std::setw;
 
#include <cstdlib> // exit function prototype
using std::exit;
 
#include "Array.h" // Array class definition
 
// default constructor for class Array (default size 10)
Array::Array( int arraySize )
{
   size = ( arraySize > 0 ? arraySize : 10 ); // validate arraySize
   ptr = new int[ size ]; // create space for pointer-based array
 
   for ( int i = 0; i < size; i++ )
      ptr[ i ] = 0; // set pointer-based array element
} // end Array default constructor
 
// copy constructor for class Array;
// must receive a reference to prevent infinite recursion
Array::Array( const Array &arrayToCopy ) 
   : size( arrayToCopy.size )
{
   ptr = new int[ size ]; // create space for pointer-based array
 
   for ( int i = 0; i < size; i++ )
      ptr[ i ] = arrayToCopy.ptr[ i ]; // copy into object
} // end Array copy constructor
 
// destructor for class Array
Array::~Array()
{
   delete [] ptr; // release pointer-based array space
} // end destructor
 
// return number of elements of Array
int Array::getSize() const
{
   return size; // number of elements in Array
} // end function getSize
 
// overloaded assignment operator;
// const return avoids: ( a1 = a2 ) = a3
const Array &Array::operator=( const Array &right )
{
   if ( &right != this ) // avoid self-assignment
   {
      // for Arrays of different sizes, deallocate original
      // left-side array, then allocate new left-side array
      if ( size != right.size )
      {
         delete [] ptr; // release space
         size = right.size; // resize this object
         ptr = new int[ size ]; // create space for array copy
      } // end inner if
 
      for ( int i = 0; i < size; i++ )
         ptr[ i ] = right.ptr[ i ]; // copy array into object
   } // end outer if
 
   return *this; // enables x = y = z, for example
} // end function operator=
 
// 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 number of elements
 
   for ( int i = 0; i < size; i++ )
      if ( ptr[ i ] != right.ptr[ i ] )
         return false; // Array contents are not equal
 
   return true; // Arrays are equal
} // end function operator==
 
 
// overloaded subscript operator for non-const Arrays;
// reference return creates a modifiable lvalue
int &Array::operator[]( int subscript )
{
   // check for subscript out-of-range error
   if ( subscript < 0 || subscript >= size )
   {
      cerr << "\nError: Subscript " << subscript 
         << " out of range" << endl;
      exit( 1 ); // terminate program; subscript out of range
   } // end if
 
   return ptr[ subscript ]; // reference return
} // end function operator[]
 
// overloaded subscript operator for const Arrays
// const reference return creates an rvalue
int Array::operator[]( int subscript ) const
{
   // check for subscript out-of-range error
   if ( subscript < 0 || subscript >= size )
   {
      cerr << "\nError: Subscript " << subscript 
         << " out of range" << endl;
      exit( 1 ); // terminate program; subscript out of range
   } // end if
 
   return ptr[ subscript ]; // returns copy of this element
} // end function 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;
} // end function 
 
// overloaded output operator for class Array 
ostream &operator<<( ostream &output, const Array &a )
{
   int i;
 
   // output private ptr-based array 
   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;
   } // end for
 
   if ( i % 4 != 0 ) // end last line of output
      output << endl;
 
   return output; // enables cout << x << y;
} // end function operator<<
 
/**************************************************************************
 * (C) Copyright 1992-2005 by Deitel & Associates, Inc. and               *
 * Pearson Education, Inc. All Rights Reserved.                           *
 *                                                                        *
 * DISCLAIMER: The authors and publisher of this book have used their     *
 * best efforts in preparing the book. These efforts include the          *
 * development, research, and testing of the theories and programs        *
 * to determine their effectiveness. The authors and publisher make       *
 * no warranty of any kind, expressed or implied, with regard to these    *
 * programs or to the documentation contained in these books. The authors *
 * and publisher shall not be liable in any event for incidental or       *
 * consequential damages in connection with, or arising out of, the       *
 * furnishing, performance, or use of these programs.                     *
 **************************************************************************/
 
 
 
// Fig. 11.8: fig11_08.cpp
// Array class test program.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
 
#include "Array.h"
 
int main()
{
   Array integers1( 7 ); // seven-element Array
   Array integers2; // 10-element Array by default
 
   // print integers1 size and contents
   cout << "Size of Array integers1 is " 
      << integers1.getSize()
      << "\nArray after initialization:\n" << integers1;
 
   // print integers2 size and contents
   cout << "\nSize of Array integers2 is " 
      << integers2.getSize()
      << "\nArray after initialization:\n" << integers2;
 
   // input and print integers1 and integers2
   cout << "\nEnter 17 integers:" << endl;
   cin >> integers1 >> integers2;
 
   cout << "\nAfter input, the Arrays contain:\n"
      << "integers1:\n" << integers1
      << "integers2:\n" << integers2;
 
   // use overloaded inequality (!=) operator
   cout << "\nEvaluating: integers1 != integers2" << endl;
 
   if ( integers1 != integers2 )
      cout << "integers1 and integers2 are not equal" << endl;
 
   // create Array integers3 using integers1 as an
   // initializer; print size and contents
   
   
   
   
   
   Array integers3( integers1 ); // invokes copy constructor
 
   cout << "\nSize of Array integers3 is "
      << integers3.getSize()
      << "\nArray after initialization:\n" << integers3;
 
   // use overloaded assignment (=) operator
   cout << "\nAssigning integers2 to integers1:" << endl;
   integers1 = integers2; // note target Array is smaller
 
   cout << "integers1:\n" << integers1
      << "integers2:\n" << integers2;
 
   // use overloaded equality (==) operator
   cout << "\nEvaluating: integers1 == integers2" << endl;
 
   if ( integers1 == integers2 )
      cout << "integers1 and integers2 are equal" << endl;
 
   // use overloaded subscript operator to create rvalue
   cout << "\nintegers1[5] is " << integers1[ 5 ];
 
   // use overloaded subscript operator to create lvalue
   cout << "\n\nAssigning 1000 to integers1[5]" << endl;
   integers1[ 5 ] = 1000;
   cout << "integers1:\n" << integers1;
 
   // attempt to use out-of-range subscript
   cout << "\nAttempt to assign 1000 to integers1[15]" << endl;
   integers1[ 15 ] = 1000; // ERROR: out of range
   return 0;
} // end main
 
/**************************************************************************
 * (C) Copyright 1992-2005 by Deitel & Associates, Inc. and               *
 * Pearson Education, Inc. All Rights Reserved.                           *
 *                                                                        *
 * DISCLAIMER: The authors and publisher of this book have used their     *
 * best efforts in preparing the book. These efforts include the          *
 * development, research, and testing of the theories and programs        *
 * to determine their effectiveness. The authors and publisher make       *
 * no warranty of any kind, expressed or implied, with regard to these    *
 * programs or to the documentation contained in these books. The authors *
 * and publisher shall not be liable in any event for incidental or       *
 * consequential damages in connection with, or arising out of, the       *
 * furnishing, performance, or use of these programs.                     *
 **************************************************************************/

Open in new window

Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

>> How can I add three more additional operators for the following program.
What operators? Added to what?

See if these links help.

Operator overloading  
http://www.parashift.com/c++-faq-lite/operator-overloading.html

C++ Operator Overloading Guidelines
http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html
Avatar of aditya86b

ASKER

suppose addition operator or subtraction
ASKER CERTIFIED SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> Chains work fine with const return references.
Yes, you're right (my head was in the clouds there); however, I still don't agree with it for the following reason...

Firstly, let's take the implementation of the std::vector's assignment operator as an example...

_Myt& operator=(const _Myt& _Right); // Does not return const reference

Secondly, it means the assignment semantics will not be the same as the standard built-in or synthesised assignment operators. This can impact ones ability to write generic code as the behaviour would be unexpected.

template <typename T>
void bar(T & t)
{
}
 
template <typename T>
void foo(T & t1, T & t2, T & t3)
{
	(t1 = t2) = t3;
	bar(t3 = t1);
}
 
struct ArrayBad
{
	const ArrayBad & operator=( const ArrayBad &right )
	{
		return *this;
	}
};
 
struct ArrayGood
{
	ArrayGood &operator=( const ArrayGood &right )
	{
		return *this;
	}
};
 
struct Default{};
 
int main()
{
	int i1, i2, i3;
	foo(i1, i2, i3);
 
	Default d1, d2, d3;
	foo(d1, d2, d3);
 
	ArrayGood ag1, ag2, ag3;
	foo(ag1, ag2, ag3);
 
	// This class has wrong assignment semantics, it doesn't behave like built-in types
	// not does the assignment operator behave like a compiler synthersised operator
	ArrayBad ab1, ab2, ab3;
	foo(ab1, ab2, ab3);
}

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>> the return value should be non-const. As it is a temporary array
What should be returned is a non-const reference to *this
>>>> What should be returned is a non-const reference to *this
No. The operator+ returns a new Array by Value.  The operator+= would return a non-const reference to this ...
>> No. The operator+ returns a new Array by Value.

Yes as it should and as I have already pointed out above where I state, "Note that you must return a copy of a new object because the standard + and - operators shouldn't modify the original objects".

However, I was refering to this comment you made...

">>>> const Array &Array::operator=( const Array &right )
I agree with evilrix that the return value should be non-const. As it is a temporary array only which only lives within the current scope"

Clearly, and operator=() should not return a temporary, it returns a reference to *this and, as we both agree, it should be non-const.

I think we are just talking at cross purposes, but I don't want to confuse aditya86b. :)
> however, I still don't agree with it for the following reason...

I agree with you, evilrix, for an Array class. I expect if Dietel had another 13 years to work on that code, they might change their position too ;-)
>>>> I agree with evilrix that the return value should be non-const.

Sorry, you are right. I was mixing up operator= and operator+ (and possibly have confused the asker).

It isn't quite easy to find an example where the const return of operator= does any harm though ...

  (a.operator=(a1)).append(12345);

wouldn't compile but I don't know whether that is a statement of relevance ...

  (a = a1).append(98765);

compiles if a is a non-const Array.
>> It isn't quite easy to find an example where the const return of operator= does any harm though
It's not so much harm as semantically incorrect in terms of it doesn't fit with the standard nor compiler synthesised operators and, as I point out, this could be problematic when writing generic code. That said, the problem it tries to address is reasonable; however, (a) is it really a problem? and (b) even if it is since you can still do it with integral and compiler synthesized types changing your own types to behave differently is just going to confuse.

So to sum up, I applaud the idea (I think, although I'd have to check, Scott Meyer advocates doing this, or something like it); however, personally I prefer my semantics consistent even if they aren't wholly correct :)