Example Of Overloading Operators
Go Up to Overloading Operator Functions Overview Index (C++)
The following example extends the class complex to create complex-type vectors. Several of the most useful operators are overloaded to provide some customary mathematical operations in the usual mathematical syntax.
Some of the issues illustrated by the example are:
- The default constructor is defined. The default constructor is provided by the compiler only if you have not defined it or any other constructor.
- The copy constructor is defined explicitly. Normally, if you have not defined any constructors, the compiler will provide one. You should define the copy constructor if you are overloading the assignment operator.
- The assignment operator is overloaded. If you do not overload the assignment operator, the compiler calls a default assignment operator when required. By overloading assignment of cvector types, you specify exactly the actions to be taken. Note that derived classes cannot inherit the assignment operator.
- The subscript operator is defined as a member function (a requirement when overloading) with a single argument. The const version assures the caller that it will not modify its argument - this is useful when copying or assigning. This operator should check that the index value is within range - a good place to implement exception handling.
- The addition operator is defined as a member function. It allows addition only for cvector types. Addition should always check that the operands' sizes are compatible.
- The multiplication operator is declared a friend. This lets you define the order of the operands. An attempt to reverse the order of the operands is a compile - time error.
- The stream insertion operator is overloaded to naturally display a cvector. Large objects that do not display well on a limited size screen might require a different display strategy.
Example Source
/* HOW TO EXTEND THE complex CLASS AND OVERLOAD THE REQUIRED OPERATORS. */ complexcomplexcomplex #include <complex> // This includes iostream using namespace std; // COMPLEX VECTORS template <class T> class cvector { int size; complex<T> *data; public: cvector() { size = 0; data = NULL; }; cvector(int i = 5) : size(i) { // DEFAULT VECTOR SIZE. data = new complex<T>[size]; for (int j = 0; j < size; j++) data[j] = j + (0.1 * j); // ARBITRARY INITIALIZATION. }; /* THIS VERSION IS CALLED IN main() */ complex<T>& operator [](int i) { return data[i]; }; /* THIS VERSION IS CALLED IN ASSIGNMENT OPERATOR AND COPY THE CONSTRUCTOR */ const complex<T>& operator [](int i) const { return data[i]; }; cvector operator +(cvector& A) { // ADDITION OPERATOR cvector result(A.size); // DO NOT MODIFY THE ORIGINAL for (int i = 0; i < size; i++) result[i] = data[i] + A.data[i]; return result; }; /* BECAUSE scalar * vector MULTIPLICATION IS NOT COMMUTATIVE, THE ORDER OF THE ELEMENTS MUST BE SPECIFIED. THIS FRIEND OPERATOR FUNCTION WILL ENSURE PROPER MULTIPLICATION. */ friend cvector operator *(T scalar, cvector& A) { cvector result(A.size); // DO NOT MODIFY THE ORIGINAL for (int i = 0; i < A.size; i++) result.data[i] = scalar * A.data[i]; return result; } /* THE STREAM INSERTION OPERATOR. */ friend ostream& operator <<(ostream& out_data, cvector& C) { for (int i = 0; i < C.size; i++) out_data << "[" << i << "]=" << C.data[i] << " "; cout << endl; return out_data; }; cvector( const cvector &C ) { // COPY CONSTRUCTOR size = C.size; data = new complex<T>[size]; for (int i = 0; i < size; i++) data[i] = C[i]; } cvector& operator =(const cvector &C) { // ASSIGNMENT OPERATOR. if (this == &C) return *this; delete[] data; size = C.size; data = new complex<T>[size]; for (int i = 0; i < size; i++) data[i] = C[i]; return *this; }; virtual ~cvector() { delete[] data; }; // DESTRUCTOR }; int main(void) { /* A FEW OPERATIONS WITH complex VECTORS. */ cvector<float> cvector1(4), cvector2(4), result(4); // CREATE complex NUMBERS AND ASSIGN THEM TO complex VECTORS cvector1[3] = complex<float>(3.3, 102.8); cout << "Here is cvector1:" << endl; cout << cvector1; cvector2[3] = complex<float>(33.3, 81); cout << "Here is cvector2:" << endl; cout << cvector2; result = cvector1 + cvector2; cout << "The result of vector addition:" << endl; cout << result; result = 10 * cvector2; cout << "The result of 10 * cvector2:" << endl; cout << result; return 0; }
Output
Here is cvector1: [0]=(0, 0) [1]=(1.1, 0) [2]=(2.2, 0) [3]=(3.3, 102.8) Here is cvector2: [0]=(0, 0) [1]=(1.1, 0) [2]=(2.2, 0) [3]=(33.3, 81) The result of vector addition: [0]=(0, 0) [1]=(2.2, 0) [2]=(4.4, 0) [3]=(36.6, 183.8) The result of 10 * cvector2: [0]=(0, 0) [1]=(11, 0) [2]=(22, 0) [3]=(333, 810)