1.43k likes | 1.57k Vues
In this chapter, you will:Learn about overloadingBecome aware of the restrictions on operator overloadingExamine the pointer thisLearn about friend functionsExplore the members and nonmembers of a classDiscover how to overload various operatorsLearn about templatesExplore how to construct fu
                
                E N D
1. CSci 152: Programming IIFall 2004 Operator Overloading
Templates 
2. In this chapter, you will:
Learn about overloading
Become aware of the restrictions on operator overloading
Examine the pointer this
Learn about friend functions
Explore the members and nonmembers of a class
Discover how to overload various operators
Learn about templates
Explore how to construct function templates and class templates
	 
3. The capability of combining data and operations on data is called encapsulation. This is the first principle of OOD. 
In Chapter 13, we also defined abstract data type (ADT) and discussed how classes in C++ implement ADT. 
In Chapter 14, we discussed how new classes could be derived from existing classes through the mechanism of inheritance and composition.
Inheritance is the second principle of OOD, as defined in Chapter 14, and encourages code reuse.
	 
4. 	WHY OPERATOR OVERLOADING IS NEEDED
Recall the class clockType as defined in Chapter 13. 
Consider the following statements.
 	clockType myClock(8,23,34);
 	clockType yourClock(4,5,30);
	myClock.printTime();
	myClock.incrementSeconds();
	if(myClock.equalTime(yourClock))
	.
	.
	.
 
5. We would like to use the following statements in place of the above statements.
cout<<myClock;
myClock++;
if(myClock == yourClock)
.
.
.
 
6. The only built-in operations on classes are the assignment operator and the member selection operator. 
Therefore, other operators cannot be applied, directly, on class objects. 
C++ allows the programmer to extend the definitions of most of the operators to work with classes 
In C++s terminology, this is called operator overloading. 
 
7. OPERATOR OVERLOADING
C++ allows the user to overload most of the operators to work effectively in a specific application. 
C++ does not allow the user to create new operators. 
Most of the existing operators can be overloaded to manipulate class objects. 
In order to overload an operator we must write functions.
The name of the function that overloads an operator is the reserved word operator followed by the operator to be overloaded. 
The following function name overloads >=
	operator>=
Operator function: The function that overloads an operator. 
8. Syntax for Operator Functions
The syntax of the heading of an operator function is
returnType  operator operatorSymbol(arguments)
The operator function is a value-returning function. 
In C++, operator is a reserved word.
To overload an operator for a class:
1. Include the function to overload the operator (that is, the operator function) in the definition of the class.
2. Write the definition of the operator function.
 
9. Overloading an Operator: Some Restrictions
When overloading an operator the following should be kept in mind.
1. 	You cannot change the precedence of an operator.
2.	The associativity cannot be changed. (For example, the associativity of the arithmetic operator addition is from left to right and it cannot be changed.)
3. Default arguments cannot be used with an overloaded operator.
4. You cannot change the number of arguments that an operator takes.
5. You cannot create new operators. Only existing operators can be overloaded. The operators that cannot be overloaded are
	.   .*   ::   ?:   sizeof
6. The meaning of how an operator works with built-in types, such as int, remains the same.
7. Operators can be overloaded either for objects of the user-defined types, or for a combination of objects of the user-defined type and objects of the built-in type. 
10. The following is a list of operators  that can be overloaded.
+	-	*	/	%	^ 	&	|	
!	&&	||	=	==	<	<=	>	
>=	!=	+=	-=	*=	/=	%=	^=	
|=	&=	<<	>>	>>=	<<=	++	--	
->*	,	->	[]	()	~	new	delete	
 
11. this Pointer
Every object of a class maintains a (hidden) pointer to itself and the name of this pointer is this. 
In C++, this is a reserved word. 
When an object invokes a member function, the this pointer of the object is referenced by the member function. 
Suppose that test is a class and it has a member function, say one. Further suppose that the definition of one looks like:
	test test::one()
	{
	   .
  		.
   	.
   	return *this;
	} 
12. 	If x and y are objects of the type test, the statement
	y = x.one();
	returns the value of the object x to object y, that is, the data members of x will be copied into the corresponding data members of y. 
When the object x invokes the function one, the pointer this in the definition of the member function one refers to the object x and so this means the address of x and *this means the value of x. 
13. Example 16-1
class thisPointerClass
{
public:
    void set(int a, int b, int c);
    void print() const;
    thisPointerClass updateXYZ();
	     //Post: x = 2 * x; y = y + 2;
	     //	  z = z * z;
    thisPointerClass(int a = 0, int b = 0, 
                     int c = 0);
private:
    int x;
    int y;
    int z;
};
 
14. void thisPointerClass::set(int a, int b, int c)
{
	   x = a;
	   y = b;
	   z = z;
}
void thisPointerClass::print() const
{
	  cout<<"x = "<<x
	      <<", y = "<<y
	      <<", z = "<<z<<endl;
}
thisPointerClass thisPointerClass::updateXYZ()
{
		x = 2 * x; 
		y = y + 2;
		z = z * z;
		return *this;
} 
15. thisPointerClass::thisPointerClass(int a, int b, 
                                   int c)
{
		x = a;
		y = b;
		z = c;
}
 
16. int main()
{
	thisPointerClass object1(3, 5, 7);		//Line 1
	thisPointerClass object2;			//Line 2
	cout<<"Object 1: ";					//Line 3
	object1.print();					//Line 4
	object2 = object1.updateXYZ();		//Line 5
	cout<<"After updating object1: ";		//Line 6
	object1.print();					//Line 7
	cout<<"Object 2: ";					//Line 8
	object2.print();					//Line 9
	return 0;
}
Output
Object 1: x = 3, y = 5, z = 7
After updating object1: x = 6, y = 7, z = 49
Object 2: x = 6, y = 7, z = 49 
17. Example 16-2
class personType
{
public:
    void print() const;
    void setName(string first, string last);
    personType& setLastName(string last);
	    //Function to set the last name
	    //Post: lastName = last;
	    //After setting the last name, a reference
	    //to the object, that is, the address of the
      //object, is returned
    personType& setFirstName(string first);
	    //Function to set the first name
	    //Post: firstName = last;
	    //After setting the first name, a reference
	    //to the object, that is, the address of the
     //object, is returned
    void getName(string& first, string& last);
    personType(string first = "", string last = ""); 
18.  private:
    string firstName; //store the first name
    string lastName;  //store the last name
};
personType& personType::setLastName(string last)
{
	lastName = last;
	 
	return *this;
}
personType& personType::setFirstName(string first)
{
	firstName = first;
	return *this;
}
 
19. int main()
{
   personType student1("Angela", "Clodfelter");  //Line 1
   personType student2;				  //Line 2
   personType student3;				  //Line 3
   cout<<"Line 4 -- Student 1: ";			  //Line 4
   student1.print();					  //Line 5
   cout<<endl;						  //Line 6
   student2.setFirstName("Shelly").setLastName("Malik"); 
									//Line 7
   cout<<"Line 8 -- Student 2: ";			  //Line 8
   student2.print();					  //Line 9
   cout<<endl;					       //Line 10
   student3.setFirstName("Chelsea");	       //Line 11
   cout<<"Line 12 -- Student 3: ";		       //Line 12
   student3.print();				       //Line 13
   cout<<endl;					       //Line 14
   student3.setLastName("Tomek");		       //Line 15
    
20. 
   cout<<"Line 16 -- Student 3: ";		       //Line 16
   student3.print);				       //Line 17
   cout<<endl;					       //Line 18
   return 0;
}
Output
Line 4 -- Student 1: Angela Clodfelter
Line 8 -- Student 2: Shelly Malik
Line 12 -- Student 3: Chelsea
Line 16 -- Student 3: Chelsea Tomek 
21. Friend Functions of Classes
A function that is defined outside the scope of a class is called a friend function. 
A friend function is a nonmember function of the class, but has access to the private data members of the class. 
To make a function friend to a class, the reserved word friend precedes the function prototype (in the class definition).
The word friend appears only in the function prototype (in the class definition), not in the definition of the friend function.
	 
22. class classIllusFriend
{
   friend void two(...);
	.
	.
	.
};
In the definition of the class classIllusFriend, two is declared as a friend of the class classIllusFriend; that is, it is a nonmember function of the class classIllusFriend. 
When you write the definition of the function two, any object of the type classIllusFriendwhich is either a local variable of two or a formal parameter of twocan access its private members within the definition of the function two.  
Because a friend function is not a member of a class, its declaration can be placed within the private, protected, or public part of the class. 
23. Definition of a friend Function
When writing the definition of the friend function, the name of the class and the scope resolution operator does not precede the name of the friend function in the function heading. 
The definition of the function two in the above class classIllusFriend is:
void two(...)
{
	.
	.
	.
}
We will place the definition of the friend function in the implementation file. 
24. Example 16-3
class classIllusFriend
{
    friend void two(classIllusFriend cLFObject);
public:
    void print();
    void setx(int a);
private:
	   int x;
};
void classIllusFriend::print()
{
	cout<<"In class classIllusFriend: x = "<<x<<endl;
}
void classIllusFriend::setx(int a)
{
		x = a;
} 
25. void two(classIllusFriend cLFObject)		//Line 1
{
    classIllusFriend localTwoObject;		//Line 2
    localTwoObject.x = 45;				//Line 3
    localTwoObject.print();			//Line 4
    cout<<endl;						//Line 5
    cout<<"Line 6: In Friend Function two accessing "
	      <<"private data member x "
	      <<localTwoObject.x<<endl;			//Line 6
	
    cLFObject.x = 88;					//Line 7
    cLFObject.print();				//Line 8
    cout<<endl;						//Line 9
    cout<<"Line 10: In Friend Function two accessing "
	      <<"private data member x "
	      <<localTwoObject.x<<endl;			//Line 10
}
 
26. int main()
{	
	classIllusFriend aObject;				//Line 11
	aObject.setx(32);					//Line 12
	cout<<"Line 13: aObject.x: ";			//Line 13
	aObject.print();					//Line 14
	cout<<endl;						//Line 15
	cout<<"*~*~*~*~*~* Testing Friend Function "
	    <<"two *~*~*~*~*~*"<<endl<<endl;	//Line 16
	two(aObject);						//Line 17
	return 0;
}
 
27. 
Output
Line 13: aObject.x: In class classIllusFriend: x = 32
*~*~*~*~*~* Testing Friend Function two *~*~*~*~*~*
In class classIllusFriend: x = 45
Line 6: In Friend Function two accessing private data member x 45
In class classIllusFriend: x = 88
Line 10: In Friend Function two accessing private data member x 45 
28. Operator Functions as Member Functions and Nonmember Functions
1. The function that overloads any of the operators (), [], ->, or = for a class must be declared as a member of the class.
2. Suppose an operator op is overloaded for a class, say OpOverClass.
a. If the leftmost operand of op is an object of a different type (that is, not of the type OpOverClass), the function that overloads the operator op for OpOverClass must be a nonmemberthat is, a friend of the class OpOverClass.
b. If the operator function that overloads the operator op for the class OpOverClass is a member of the class OpOverClass, then when applying op on objects of the type OpOverClass, the leftmost operand of op must be of the type OpOverClass. 
29. Except for some of the operators, as explained above, most of the operators can be overloaded either as member functions or as nonmember functions. 
The following class is used to illustrate operator overloading.
class OpOverClass
{
		.
		.
		.
private:
   int a;
   int b;
};
OpOverClass x;
OpOverClass y;
OpOverClass z;.  
30. Binary Operators as Member Functions
Suppose that the binary operator + is overloaded for the class OpOverClass.
Overloading + as a Member Function
Suppose that + is overloaded as a member function of the class OpOverClass.
The name of the function to overload + for the class OpOverClass is 
operator+
	 
31. Since x and y are objects of the type OpOverClass, we can perform the operation
	x + y
The compiler translates this expression into the following expression:
	x.operator+(y)
In this expression, there is only one argument to the function operator+, which is y. 
In the above statement, operator+ has direct access to the private members of the object x.  
The first argument to operator+ is the object that is invoking the function operator+ and the second argument is passed as a parameter to this function. 
32. Suppose that the operator + adds the corresponding data members of the objects. 
The result of the expression
	x + y
	is an object of the type OpOverClass. 
The return type of the operator function operator+ is of the type OpOverClass. 
The function prototype of operator+ in the definition of the class OpOverClass is:
OpOverClass operator+(const OpOverClass&) const;
 
33. OpOverClass OpOverClass::operator+
 		(const OpOverClass& otherObject) const
{
		OpOverClass temp;
		temp.a = a + otherObject.a;
		temp.b = b + otherObject.b;
		return temp;
} 
34. General Syntax to Overload Binary (Arithmetic) Operators as Member Functions
Function Prototype (to be included in the definition of the class):
returnType operator op(className);
op stands for the binary operator to be overloaded. 
returnType is the type of the value returned by the function. 
className is the name of the class for which the operator is being overloaded.
 
35. Function Definition:
returnType className::operator op
 			(const className& otherObject) const
{
	//algorithm to perform the operation
	return (value);
}
 
36. Example 16-4
class OpOverClass
{
public:
    void print() const;
		//Overload arithmetic operators
    OpOverClass operator+(const OpOverClass&) const;
    OpOverClass operator*(const OpOverClass&) const;
    OpOverClass(int i = 0, int j = 0);
private:
    int a;
    int b;
};
void OpOverClass::print() const
{
	cout<<"("<<a<<", "<<b<<")";
} 
37. OpOverClass::OpOverClass(int i, int j)
{
	a = i;
	b = j;
}
		
OpOverClass OpOverClass::operator+
  			(const OpOverClass& right) const
{
	OpOverClass temp;
	temp.a = a + right.a;
	temp.b = b + right.b;
	return temp;
}
OpOverClass OpOverClass::operator*
  			(const OpOverClass& right) const
{
	OpOverClass temp;
	temp.a = a * right.a;
	temp.b = b * right.b;
	return temp;
} 
38. int main()
{
	OpOverClass u(23, 45); 	//Line 1
	OpOverClass v(12,10);		//Line 2
	OpOverClass w1;			//Line 3
	OpOverClass w2;			//Line 4
	cout<<"Line 5: u = ";		//Line 5
	u.print();			//Line 6; output u
	cout<<endl;			//Line 7
	cout<<"Line 8: v = ";		//Line 8
	v.print();			//Line 9; output v
	cout<<endl;			//Line 10
	w1 = u + v;		//Line 11; add u and v
	
	cout<<"Line 12: w1 = ";	//Line 12
	w1.print();			//Line 13; output w1
	cout<<endl;			//Line 14
 
39. 
	w2 = u * v;	//Line 15; multiply u and v
	
	cout<<"Line 16: w2 = ";	//Line 16
	w2.print();			//Line 17; output w2
	cout<<endl;			//Line 18
	return 0;
}
Output
Line 5: u = (23, 45)
Line 8: v = (12, 10)
Line 12: w1 = (35, 55)
Line 16: w2 = (276, 450)
 
40. Overloading Relational Operators as Member Functions
We overload the equality operator, ==, for the class OpOverClass.
Since the result of a relational operator is either true or false, the returnType of the function operator== is Boolean. 
The syntax of the function prototype to be included in the definition of the class OpOverClass is:
bool operator==(const OpOverClass&) const; 
 
41. bool OpOverClass ::operator==
 			(const OpOverClass& right) const
{
	return(a == right.a && b == right.b);
}
 
42. General Syntax to Overload Binary Relational Operators as Member Functions
Function Prototype
 bool operator op(const className&) const;
op is the relational operator that is being overloaded.
className is the name of the class for the operator op is being overloaded.
Function Definition:
bool className::operator op(const className& right) 
                                           const
{
	//Compare and return the value 
} 
43. Binary Operators as Nonmember Functions
Suppose that + is overloaded as a nonmember function of the class OpOverClass. 
Suppose that the following operation is to be performed.
	x + y
This expression is compiled as
	operator+(x,y)
The function operator+ has two arguments. 
The function operator+ is neither a member of the object x nor a member of the object y. 
The objects to be added are passed as arguments to the function operator+. 
44. To include the operator function operator+ as a nonmember of the class in the definition of the class the reserved word friend must appear before the function heading. 
The function operator+ must have two arguments. 
To include operator+ as a nonmember in the definition of the the class OpOverClass its prototype in the definition of OpOverClass is
   friend OpOverClass operator+(const OpOverClass&, 
 				           const OpOverClass&); 
45. 
OpOverClass operator+(
                    const OpOverClass& firstObject, 
     		    const OpOverClass& secondObject)
{
	OpOverClass temp;
	temp.a = firstObject.a + secondObject.a;
	temp.b = firstObject.b + secondObject.b;
	return temp;
}
 
46. In the above definition, we add the corresponding data members of firstObject and secondObject and store the result in temp. 
Recall that the private members of a class are local to the class and therefore cannot be accessed outside the class. 
Following this rule, since operator+ is not a member of the class OpOverClass, in the definition of the function operator+, expressions such as firstObject.a must be illegal since a is a private member of firstObject. 
Since operator+ was declared as a friend function of the class OpOverClass, an object of the type OpOverClass can access its private members in the definition of operator+.  
In the function heading, the name of the class, that is, OpOverClass and the scope resolution operator is not included before the name of the function operator+ since the function operator+ is not a member of the class. 
47. General Syntax to Overload Binary (Arithmetic) Operators as Nonmember Functions
Function Prototype (to be included in the definition of the class):
friend returnType operator op(const className&, 
 				         const className&);
op stands for the binary operator to be overloaded.  
returnType is the type of the value returned by the function.
className is the name of the class for which the operator is being overloaded.
 
48. Function Definition
returnType operator op(const className& firstObject,
   			      const className& secondObject)
{
	//algorithm to perform the operation
	return (value);
}
 
49. Overloading Relational Operators as Nonmember Functions
We overload the equality operator, ==, for the class OpOverClass.
The return type of the function operator== is Boolean. 
Function Prototype 
friend bool operator==(const OpOverClass&, 
 			       const OpOverClass&); 
 
50. Function Definition
bool operator==(const OpOverClass& firstObject,
 		    const OpOverClass& secondObject)
{
	return(firstObject.a == secondObject.a && 
            firstObject.b == secondObject.b);
}
 
51. General Syntax to Overload Binary Relational Operators as Nonmember Functions
Function Prototype (to be included in the definition of the class):
friend bool operator op(const className&, 
                        const className&);
op is the relational operator that is being overloaded.
className is the name of the class for the operator op is being overloaded.
Function Definition:
bool operator op (const className& firstObject, 
   			const className& secondObject)
{
	//Compare and return the value 
} 
52. Overloading Stream Insertion (<<) and Extraction (>>) Operators
The operator function that overloads the insertion operator << or the extraction operator  >> for a class must be a nonmember of that class. 
	Consider the following expression. 
	cin>>x
In this expression, the left most operand of >>, that is, cin  is an istream variable, not an object of the type OpOverClass. 
Since the left most operand of >> is not an object of the type OpOverClass, the operator function that overloads the extraction operator for OpOverClass must be a nonmember of the class OpOverClass. 
Similarly, the operator function that overloads the stream insertion operator for OpOverClass must be a nonmember function of OpOverClass. 
53. Overloading the Stream Insertion Operator (<<)
	
	The general syntax to overload the stream insertion operator << for a class is:
Function Prototype (to be included in the definition of the class):
friend ostream& operator<<(ostream&, 
                           const className& );
Function Definition:
ostream& operator<<(ostream& osObject, 
                    const className&  object)
{
	 //local declaration if any
	 //Output members of the object
	 //osObject<<. . .
	 //return stream object
 	return osObject;
} 
54. Overloading the Stream Extraction Operator (>>)
The general syntax to overload the stream extraction operator >> for a class is:
Function Prototype:
friend istream& operator>>(istream&, className&);
Function Definition:
istream& operator>>(istream& isObject, 
                    className&  object)
{
	 //local declaration if any
	 //Read data into the object 
	 //isObject>>. . .
	 //return stream object
 	return isObject;
} 
55. Example 16-6
class OpOverClass
{
		//overload stream insertion and extraction operators
    friend ostream& operator<<(ostream&, 
                               const OpOverClass&);
    friend istream& operator>>(istream&, 
                               OpOverClass&);
public:
		//overload arithmetic operators
    OpOverClass operator+(const OpOverClass&) const;
    OpOverClass operator*(const OpOverClass&) const;
    OpOverClass(int i = 0, int j = 0);
private:
    int a;
    int b;
};
 
56. 	//Definitions of the functions operator+, operator*, 
	//and the constructor are the same as in Example 16-4
ostream& operator<<(ostream& os, 
                    const OpOverClass& right)
{
	os<<"("<<right.a<<", "<<right.b<<")";
	return os;
}
istream& operator>>(istream& is, OpOverClass& right)
{
	is>>right.a>>right.b;
	return is;
}
 
57. int main()
{
	OpOverClass u(23, 45);			//Line 1
	OpOverClass v;					//Line 2
	cout<<"Line 3: u : "<<u<<endl;		//Line 3
	cout<<"Line 4: Enter two integers: ";	//Line 4
	cin>>v;						//Line 5
	cout<<endl;					//Line 6
	cout<<"Line 7: v : "<<v<<endl;		//Line 7
	cout<<"Line 8: u + v : "<<u + v<<endl;	//Line 8
	cout<<"Line 9: u * v : "<<u * v<<endl;	//Line 9
	return 0;
}
 
58. 
Sample Run: In this sample run, the user input is in red.
Line 3: u = (23, 45)
Line 4: Enter two integers: 5 6
Line 7: v = (5, 6)
Line 8: u + v = (28, 51)
Line 9: u * v = (115, 270)
 
59. Overloading the Assignment Operator (=)
General Syntax to Overload the Assignment Operator = for a Class
Function Prototype:
const className& operator=(const className&);
 
60. Function Definition:
const className& className::operator=
                     (const className& rightObject)
{
	 //local declaration, if any
	 
	if( this != &rightObject)  //avoid self-assignment
	{
      //algorithm to copy the rightObject into this object
 }
	
  	 //return the object assigned
 	return *this;
}
 
61. Suppose that the assignment operator, =, is overloaded for the class OpOverClass. 
The statement
	x = y;
	is equivalent to the statement
	x.operator=(y);
Consider the statement
	x = y = z; 
Because the associativity of the operator = is from right to left, this statement is equivalent to the statement
	x.operator=(y.operator=(z));			//Line B
We must first execute the expression
	y.operator=(z)
 
62. The value returned by the expression
	y.operator=(z) 
	will become the parameter to the function operator= so as to assign a value to the object x. 
Because the formal parameter to the function operator= is a reference parameter, the expression
	y.operator=(z)
	must return a reference to the object, rather than its value. 
Now consider the statement
	x = x;
Here we are trying to copy the value of x into x; that is, this statement is a self-assignment. 
We must prevent such statements because they waste computer time. 
The body of the function operator= does prevent such assignments.  
63. Consider the if statement in the body of the operator function operator=: 
	if(this != &rightObject)  //avoid self-assignment
	{
       //algorithm to copy the rightObject into this object
	}
The statement
	x = x;
	is compiled into the statement
	x.operator=(x);
In the expression
	this != &rightObject
	this means the address of x, and &rightObject also means the address of x. Thus, the expression will evaluate to false and, the body of the if statement will be skipped. 
64. Overloading Unary Operators
1.	If the operator function is a member of the class, it has no parameters. 
2.	If the operator function is a nonmember, that is, a friend function of the class it has one parameter.
 
65. Overloading Increment (++) and Decrement (--) Operators
The increment operator has two forms, pre-increment (++u) and post-increment (u++), where u is a variable, say of the type int. 
In the case of pre-increment (++u), the value of the variable (u) is incremented by 1 before using the value of u in an expression and in the case of post-increment the value of u is used in the expression before it is incremented by 1. 
Pre-increment
To overload the pre-increment operator, in the function definition first we increment the value of the object and then use the this pointer to return the value of the object. 
 
66. Suppose that we overload the pre-increment operator for the class OpOverClass. Also suppose that the operator function operator++ is a member of the class OpOverClass. Then the operator function operator++ has no arguments. Since the operator function operator++ has no arguments, we use the this pointer to return the incremented value of the object. 
OpOverClass OpOverClass::operator++()
{
	//increment the object
  ++a;
  ++b;
  return *this; //return the incremented value of the object
} 
67. The General Syntax to Overload the Pre-increment Operator ++ As a Member Function
Function Prototype (to be included in the definition of the class):
className operator++();
Function Definition:
className className::operator++()
{
     //increment the value of the object by 1
   return *this;
}
 
68. 
The operator function to overload the pre-increment operator can also be a nonmember of the class OpOverClass.
OpOverClass operator++(OpOverClass& incObj)
{
	//increment the object
 (incObj.a)++;
 (incObj.b)++;
 return incObj; //return the incremented value of the object
} 
69. General Syntax to Overload the Pre-increment Operator ++ as a Nonmember Function
Function Prototype:
friend className operator++(className&);
Function Definition:
className operator++(className& incObj)
{
     //increment incObj by 1
   return incObj;
}
 
70. Overloading the Post-increment Operator
Overload the post-increment operator for the class OpOverClass. 
In both cases, pre- and post-increment, the name of the operator function is the operator++. 
To distinguish between pre- and post-increment operator overloading, we use a dummy parameter (of the type int) in the function heading of the operator function. 
The function prototype for the post-increment operator for the class OpOverClass is
OpOverClass operator++(int);
 
71. 	The statement 
	x++;
	is compiled by the compiler in the statement
	x.operator++(0);
	and so the function operator++ with a parameter executes. 
The parameter 0 is used merely to distinguish between the pre- and post-increment operator functions.
The steps required to implement this function are:
1. Save the value of the objectsay, in temp.
2. Increment the value of the object.
3. Return the value that was saved in temp.
 
72. 
The function definition of the post-increment operator for the class OpOverClass is
OpOverClass OpOverClass::operator++(int u)
{
   OpOverClass temp = *this;  //use this pointer to copy 
       			  	//the value of the object
     			       //increment the object   
   a++;
   b++;
   return temp;	//return the old value of the object
}
 
73. The General Syntax to Overload the Post-increment Operator ++ as a Non Member Function
Function Prototype (to be included in the definition of the class):
friend className operator++(className&, int);
Function Definition:
className operator++(className& incObj, int u)
{
   className temp = incObj;  //copy incObj into temp 
   
      //increment incObj
   return temp;	//return the old value of the object
} 
74. //Definition of the class OpOverClass
//The increment, decrement, arithmetic, and relational
//operator functions are members of the class.
class OpOverClass
{	//overload the stream insertion and extraction operators   
friend ostream& operator<<(ostream&, const OpOverClass&);
friend istream& operator>>(istream&, OpOverClass&);
public:
	  //overload the arithmetic operators
   OpOverClass operator+(const OpOverClass&) const;
   OpOverClass operator-(const OpOverClass&) const;
   OpOverClass operator*(const OpOverClass&) const;
   OpOverClass operator/(const OpOverClass&) const;
	//overload the increment and decrement operators
   OpOverClass operator++();  	//pre-increment
   OpOverClass operator++(int);  	//post-increment
   OpOverClass operator--();  	//pre-decrement
   OpOverClass operator--(int);  	//post-decrement
	 
75. 
	//overload the relational operators
   bool operator==(const OpOverClass&) const;
   bool operator!=(const OpOverClass&) const;
   bool operator<=(const OpOverClass&) const;
   bool operator<(const OpOverClass&) const;
   bool operator>=(const OpOverClass&) const;
   bool operator>(const OpOverClass&) const;
		//constructors
   OpOverClass();
   OpOverClass(int i, int j);
	//include other functions as needed
private:
	int a;
	int b;
}; 
76. //Definition of the class OpOverClass
//The increment, decrement, arithmetic, and relational
//operator functions are nonmembers of the class.
class OpOverClass
{	
   //overload the stream insertion and extraction operators   
friend ostream& operator<<(ostream&, const OpOverClass&);    
  friend istream& operator>>(istream&, OpOverClass&);	
			//overload the arithmetic operators     
   friend OpOverClass operator+(const OpOverClass&, 
 					  const OpOverClass&);
   friend OpOverClass operator-(const OpOverClass&, 
 					  const OpOverClass&);
   friend OpOverClass operator*(const OpOverClass&, 
 					  const OpOverClass&);
   friend OpOverClass operator/(const OpOverClass&, 
 					  const OpOverClass&);
	//overload the increment and decrement operators
   friend OpOverClass operator++(OpOverClass&);  	
   friend OpOverClass operator++(OpOverClass&, int);    
   friend OpOverClass operator--(OpOverClass&);  	
   friend OpOverClass operator--(OpOverClass&, int);   
77. 		//overload the relational operators
   friend bool operator==(const OpOverClass&, 
 				  const OpOverClass&);
   friend bool operator!=(const OpOverClass&, 
 				  const OpOverClass&);
   friend bool operator<=(const OpOverClass&, 
 				  const OpOverClass&);
   friend bool operator<(const OpOverClass&, 
 				  const OpOverClass&);
   friend bool operator>=(const OpOverClass&, 
 				   const OpOverClass&);
   friend bool operator>(const OpOverClass&, 
 				  const OpOverClass&);
public:
		//constructors
    OpOverClass();
    OpOverClass(int i, int j);
	//include other functions as needed
private:
	int a;
	int b;
}; 
78. Operator Overloading: Member Versus Nonmember
Certain operators must be overloaded as member functions of the class, and some must be overloaded as nonmember (friend) functions. 
The binary arithmetic operator + can be overloaded as a member function or a nonmember function. 
If you overload + as a member function, then the operator + has direct access to the data members of one of the objects, and you need to pass only one object as a parameter. 
If you overload + as a nonmember function, then you must pass both objects as parameters. 
Overloading + as a nonmember could require additional memory and computer time to make a local copy of the data. 
For efficiency purposes, wherever possible, you should overload operators as member functions. 
79. 
Classes and Pointer Data Members (Revisited)
	1. Explicitly overload the assignment operator
	2. Include the copy constructor
	3. Include the destructor
Operator Overloading: One Final Word
 
80. PROGRAMMING EXAMPLE: CLOCKTYPE
Chapter 13 defined a class clockType to implement the time of day in a program. 
We implemented the operations print time, increment time, and compare two times for equality using functions. 
This example redefines the class clockType. 
It also overloads the stream insertion and extraction operators for easy input and output, relational operators for comparisons, and the increment operator to increment the time by one second. 
The program that uses the class clockType requires the user to input the time in the form hr:min:sec. 
 
81. //Header file newClock.h
#ifndef H_newClock
#define H_newClock
class clockType
{
    friend ostream& operator<< (ostream&, 
                                    const clockType&);
    friend istream& operator>> (istream&, clockType&);
public:
    void setTime(int hours, int minutes, int seconds);
	//Function to set the private data members 
	//hr, min, and sec 
	//Post: hr = hours; min = minutes; sec = seconds
    void getTime(int& hours, int& minutes, int& seconds);
	//Function to return the time
	//Post: hours = hr; minutes = min; seconds = sec;
    clockType operator++();    
	//Overload the pre-increment operator
  	//Post: Time is incremented by one second 
82.     bool operator==(const clockType& otherClock) const; 
	//Overload the equality operator
	//Function returns true if the time is equal 
	//to otherTime, otherwise it returns the value false
    bool operator<=(const clockType& otherClock) const;
	//Overload the less than or equal to operator
	//Function returns true if the time is less 
	//than or equal to otherTime, otherwise it returns
	//the value false
    clockType(int hours = 0, int minutes = 0, 
              int seconds = 0);  
	//Constructor to initialize the object with the
	//values specified by the user. If no values are
	// specified, default values are assumed.
	//Post: hr = hours; min = minutes; sec = seconds
private: 
    int hr;  //variable to store the hours
    int min; //variable to store the minutes
    int sec; //variable to store the seconds
};
 
83. //overload the preincrement operator
clockType clockType::operator++()
{
    	sec++;  			//Step a
	if(sec > 59)  		//Step b
	{
	   sec = 0;			//Step b.1
	   min++;    		//Step b.2
	   if(min > 59)		//Step b.3
	   {
		min = 0;		//Step b.3.1
		hr++;			//Step b.3.2
		if(hr > 23)		//Step b.3.3
		   hr = 0;		//Step b.3.3.1
	   }
	}
   
	return *this;   		//Step c
} 
84. //overload the equality operator
bool clockType::operator==
               (const clockType& otherClock) const
{
     return(hr == otherClock.hr && min == otherClock.min
		 && sec == otherClock.sec);
}
//overload the less than or equal to operator
bool clockType::operator<=
              (const clockType& otherClock) const
{
   return((hr < otherClock.hr) ||
	    (hr == otherClock.hr && min < otherClock.min) ||
	    (hr == otherClock.hr && min == otherClock.min &&
	       sec <= otherClock.sec));
}
 
85. //constructor with parameters
clockType::clockType(int hours, int minutes, 
                     int seconds)
{
	if(0 <= hours && hours < 24)
	   hr = hours;
	else 
	   hr = 0;
	if(0 <= minutes && minutes < 60)
	   min = minutes;
	else 
	   min = 0;
	if(0 <= seconds && seconds < 60)
	   sec = seconds;
	else 
	   sec = 0;
}
 
86. void clockType::setTime(int hours, int minutes, 
                        int seconds)
{
	if(0 <= hours && hours < 24)
	   hr = hours;
	else 
	   hr = 0;
	if(0 <= minutes && minutes < 60)
	   min = minutes;
	else 
	   min = 0;
	if(0 <= seconds && seconds < 60)
	   sec = seconds;
	else 
	   sec = 0;
}
 
87. void clockType::getTime(int& hours, int& minutes, 
                        int& seconds)
{
	hours = hr;
	minutes = min;
	seconds = sec;
}
 
88. The time must be output in the form
hh:mm:ss
//overload the stream insertion operator
ostream& operator<< (ostream& osObject, 
                     const clockType& timeOut)
{
	if(timeOut.hr < 10)
	   osObject<<'0';
	osObject<<timeOut.hr<<':';
	
 	if(timeOut.min < 10)
	   osObject<<'0';
	osObject<<timeOut.min<<':';
	
	if(timeOut.sec < 10)
	   osObject<<'0';
	osObject<<timeOut.sec;
	return osObject;	//return the ostream object
} 
89. The input to the program is of the form
hh:mm:ss
//overload the stream extraction operator
istream& operator>> (istream& isObject, 
                     clockType& timeIn)
{
	char ch;
	isObject>>timeIn.hr;	   //Step a
	isObject.get(ch);  //Step b; read and discard :
	isObject>>timeIn.min;    //Step c
	isObject.get(ch);  //Step d; read and discard :
	isObject>>timeIn.sec;    //Step e
	return isObject;		   //Step f
} 
90. //Program that uses the class clockType 
#include <iostream>
#include "newClock.h"
using namespace std;
int main()
{
	clockType myClock(5,6,23);			//Line 1
	clockType yourClock;				//Line 2
	cout<<"Line 3: myClock = "<<myClock<<endl; //Line 3
	cout<<"Line 4: yourClock = "<<yourClock<<endl;	
								//Line 4
	cout<<"Line 5: Enter time in the form "
	    <<"hr:min:sec ";				//Line 5
	cin>>myClock;					//Line 6
	cout<<"Line 7: The new time of myClock = "
	    <<myClock<<endl;				//Line 7
	++myClock;						//Line 8
	cout<<"Line 9: After increment the time, myClock = "
	    <<myClock<<endl;				//Line 9 
91. 
	yourClock.setTime(13,35,38);		//Line 10
	cout<<"Line 11: After setting the time, yourClock = "
	    <<yourClock<<endl;				//Line 11
	if(myClock == yourClock)			//Line 12
	   cout<<"Line 13: The times of myClock and "
		 <<"yourClock are equal"<<endl;	//Line 13
	else							//Line 14
	   cout<<"Line 15: The times of myClock and "
		 <<"yourClock are not equal"<<endl;	//Line 15
	if(myClock <= yourClock)			//Line 16
	   cout<<"Line 17: The time of myClock is less "
		 <<"than or equal to "<<endl
		 <<"the time of yourClock"<<endl;	//Line 17
	else							//Line 18
	   cout<<"Line 19: The time of myClock is "
		 <<"greaterthan the time of yourClock"
		 <<endl;					//Line 19
	return 0;
} 
92. 
Sample Run In this sample run, the user input is in red.
Line 3: myClock = 05:06:23
Line 4: yourClock = 00:00:00
Line 5: Enter the time in the form hr:min:sec 4:50:59
Line 7: The new time of myClock = 04:50:59
Line 9: After increment the time, myClock = 04:51:00
Line 11: After setting the time, yourClock = 13:35:38
Line 15: The times of myClock and yourClock are not equal
Line 17: The time of myClock is less than or equal to
the time of yourClock 
93. PROGRAMMING EXAMPLE: COMPLEX NUMBERS
A number of the form a + ib, where i2 = -1, and a and b are real numbers, is called a complex number. We call a the real part and b the imaginary part of a + ib. Complex numbers can also be represented as ordered pairs (a, b). The addition and multiplication of complex numbers is defined by the following rules:
(a + ib) + (c + id) = (a + c) + i(b + d)
 (a + ib) * (c + id) = (ac - bd) + i(ad + bc)
Using the ordered pair notation
(a + ib) + (c + id) = (a + c) + i(b + d)
 (a + ib) * (c + id) = (ac - bd) + i(ad + bc)
	 
94. //Specification file complexType.h
#ifndef H_complexNumber
#define H_complexNumber
class complexType
{
   friend ostream& operator<< (ostream&, const complexType&);
   friend istream& operator>> (istream&,  complexType&);
public:
    void setComplex(const double& real, 
                    const double& imag);
	
    complexType(double real = 0, double imag = 0);  
    complexType operator+(const complexType& 
                                otherComplex) const; 
     complexType operator*(const complexType& 
                            otherComplex) const;
    bool operator==(const complexType& otherComplex) const;
private:
    double realPart;      
    double imaginaryPart; 
};
#endif 
95. To output the complex number in the form
(a, b)
where a is the real part and b is the imaginary part
ostream& operator<<(ostream& osObject, 
                    const complexType& complex)
{
	osObject<<"(";				//Step a
     osObject<<complex.realPart;	//Step b
     osObject<<", ";				//Step c
     osObject<<complex.imaginaryPart;	//Step d
     osObject<<")";				//Step e
	return osObject;	//Return the ostream object
}
 
96. Now the input is of the form, say
(3, 5)
istream& operator>> (istream& isObject, 
                     complexType& complex)
{
	char ch;
	isObject>>ch;                     //Step a
	isObject>>complex.realPart;       //Step b
	isObject>>ch;                     //Step c
	isObject>>complex.imaginaryPart;  //Step d
	isObject>>ch;                     //Step e
	return isObject; //Return the istream object
} 
97. bool complexType::operator==(const complexType& 
                                     otherComplex) const
{
	return(realPart == otherComplex.realPart && 
		 imaginaryPart == otherComplex.imaginaryPart);
}
//constructor 
complexType::complexType(double real, double imag)
{
	realPart = real;
	imaginaryPart = imag;
}
void complexType::setComplex(const double& real, 
                             const double& imag)
{
	realPart = real;
	imaginaryPart = imag;
}
 
98. //overload the operator +
complexType complexType::operator+
 		   (const complexType& otherComplex) const
{
	complexType temp;
	temp.realPart = realPart + otherComplex.realPart;
	temp.imaginaryPart = imaginaryPart 
                          + otherComplex.imaginaryPart;
	return temp;
}
 
99. 
//overload the operator *
complexType complexType::operator*
 			(const complexType& otherComplex) const
{
   complexType temp;
   temp.realPart = (realPart * otherComplex.realPart) -
             (imaginaryPart * otherComplex.imaginaryPart);
   temp.imaginaryPart = (realPart *  
                         otherComplex.imaginaryPart) +
                       (imaginaryPart * 
                               otherComplex.realPart);
   return temp;
} 
100. //Program that uses the class complexType
#include <iostream>
#include "complexType.h"
using namespace std;
int main()
{
	complexType num1(23,34);			//Line 1
	complexType num2;				//Line 2
	complexType num3;				//Line 3
	cout<<"Line 4: Num1 = "<<num1<<endl;	//Line 4
	cout<<"Line 5: Num2 = "<<num2<<endl;	//Line 5
	cout<<"Line 6: Enter the complex number "
	    <<"in the form (a,b) ";			//Line 6
	cin>>num2;						//Line 7
	cout<<endl;					//Line 8 
101. 	cout<<"Line 9: New value of num2 = "
	    <<num2<<endl;				//Line 9
	num3 = num1 + num2;				//Line 10
	
	cout<<"Line 11: Num3 = "<<num3<<endl;	//Line 11
	cout<<"Line 12: "<<num1<<" + "<<num2
	    <<" = "<<num1 + num2<<endl;		//Line 12
	cout<<"Line 13: "<<num1<<" * "<<num2
	    <<" = "<<num1 * num2<<endl;		//Line 13
	return 0;	
}
 
102. 
Sample Run: In this sample run, the user input is in red.
Line 4: Num1 = (23, 34)
Line 5: Num2 = (0, 0)
Line 6: Enter the complex number in the form (a,b) (3,4)
Line 9: New value of num2 = (3, 4)
Line 11: Num3 = (26, 38)
Line 12: (23, 34) + (3, 4) = (26, 38)
Line 13: (23, 34) * (3, 4) = (-67, 194) 
103. OVERLOADING THE ARRAY INDEX (SUBSCRIPT) OPERATOR ([])
The function to overload the operator [] for a class must be a member of the class. 
Since an array can be declared as constant or non-constant, we need to overload the operator [] to handle both the cases. 
The syntax to declare the operator function operator[] as a member of a class for non-constant arrays is:
	Type& operator[](int index);
The syntax to declare the operator function operator[] as a member of a class for constant arrays is:
	const Type& operator[](int index) const;
	where Type is the data type of the array elements. 
104. Suppose classTest is a class that has an array data member. The definition of classTest to overload the operator function operator [] is: 
class classTest
{
public:
    Type& operator[](int index); 
      //overload the operator for nonconstant arrays
    const Type& operator[](int index) const;
       //overload the operator for constant arrays
		.
		.	
		.
private:
    Type *list;  //pointer to the array
    int   arraySize;
};
 where Type is the data type of the array elements. 
105. //overload the operator [] for nonconstant arrays
Type& classTest::operator[](int index) 
{
   assert(0 <= index && index < arraySize);
   return(list[index]);  //return a pointer of the 
           		    //array component
}
      //overload the operator [] for constant arrays
const Type& classTest::operator[](int index) const
{
   assert(0 <= index && index < arraySize);
   return(list[index]);  //return a pointer of the 
 			   	     //array component
} 
106. 	classTest list1;
	classTest list2;
	const classTest list3;
 
In the case of the statement
	list1[2] = list2[3];
	the body of the operator function operator[] for nonconstant arrays is executed. 
In the case of the statement
	list1[2] = list3[5];
	first the body of the operator function operator[] for constant arrays is executed because list3 is a constant array. Next, the body of the operator function operator[] for nonconstant arrays is executed to complete the execution of the assignment statement.    
107. PROGRAMMING EXAMPLE: newString
 Recall that
1. A C string is a sequence of one or more characters,
2. C strings are enclosed in double quote marks,
3. C strings are null terminated, and
4. C strings stored in character arrays. 
In this example, by a string we mean a C string.
The only allowable aggregate operations on strings are input and output. 
To use other operations, the programmer need to include the header file cstring, which contains the specification of many functions for string manipulation.
We define a class for string manipulation and at the same time to further illustrate operator overloading.  
108. //Header file myString.h
#ifndef H_myString
#define H_myString
#include <iostream>
using namespace std;
class newString
{
	  //overload the stream insertion and extraction operators
    friend ostream& operator<<(ostream&, 
                                      const newString&);
    friend istream& operator>>(istream&, newString&);
public:
    const newString& operator=(const newString&); 
	//overload the assignment operator
    newString(const char *); 
 	//constructor; conversion from the char string
    newString();  
 	//default constructor to initialize the string to null
    newString(const newString&); 
 	//copy constructor 
109.     ~newString(); 
 	//destructor
    char &operator[] (int);      
    const char &operator[](int) const;
	  	//overload the relational operators
    bool operator==(const newString&) const;
    bool operator!=(const newString&) const;
    bool operator<=(const newString&) const;
    bool operator<(const newString&)  const;
    bool operator>=(const newString&) const;
    bool operator>(const newString&)  const;
private:
    char *strPtr;  //pointer to the char array 
    		     //that holds the string
    int strLength; //data member to store the length 
 		     //of the string
};
#endif   
110. 
//Implementation file myString.cpp
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cassert>
#include "myString.h"
using namespace std; 
111.  //constructor: conversion from the char string to newString
newString::newString(const char *str) 
{
   strLength = strlen(str);
   strPtr = new char[strLength+1]; 	//allocate
  			//memory to store the char string
   
   assert(strPtr != NULL);
   strcpy(strPtr,str);  //copy string into strPtr
}
//default constructor to store the null string
newString::newString() 
{
	strLength = 1;
	strPtr = new char[1];
	assert(strPtr != NULL);
	strcpy(strPtr,"");
} 
112. 		//copy constructor
newString::newString(const newString& rightStr)
{
	strLength = rightStr.strLength;
	strPtr = new char[strLength + 1];
	assert(strPtr != NULL);
	strcpy(strPtr, rightStr.strPtr);
}
newString::~newString()  //destructor
{
	delete [] strPtr;
}
   
113.   	//overload the assignment operator
const newString& newString::operator=
                       (const newString& rightStr)
{
	if(this != &rightStr) //avoid self-copy
	{
	   delete [] strPtr;
	   strLength = rightStr.strLength;
	   strPtr = new char[strLength + 1];
	   assert(strPtr != NULL);
	   strcpy(strPtr, rightStr.strPtr);
	}
	return *this; 
}
char& newString::operator[] (int index)
{
	assert(0 <= index && index < strLength);
	return strPtr[index];
}
 
114. const char& newString::operator[](int index) const
{
	assert(0 <= index && index < strLength);
	return strPtr[index];
}
//overload the relational operators
bool newString::operator==
                 (const newString& rightStr) const
{
	return(strcmp(strPtr, rightStr.strPtr) == 0);
}
bool newString::operator<(const newString& rightStr) const
{
	return(strcmp(strPtr, rightStr.strPtr) < 0);
}
bool newString::operator<=(const newString& rightStr) 
                                                   const
{
	return(strcmp(strPtr, rightStr.strPtr) <= 0);
}
 
115. bool newString::operator>(const newString& rightStr) const
{
	return(strcmp(strPtr, rightStr.strPtr) > 0);
}
bool newString::operator>=(const newString& rightStr) const
{
	return(strcmp(strPtr, rightStr.strPtr) >= 0);
}
bool newString::operator!=(const newString& rightStr) 
                                                  const
{
	return(strcmp(strPtr, rightStr.strPtr) != 0);
}
 
116. 
 	//overload the stream insertion operator << 
ostream& operator<<(ostream& osObject, 
                    const newString& str)
{
	osObject<<str.strPtr;
	return osObject;
}
//overload the stream extraction operator >> 
istream& operator>>(istream& isObject, 
                    newString& str)
{
	char temp[81];
	isObject>>setw(81)>>temp;
	str = temp;
	return isObject;
} 
117. The conversion constructor is a single parameter function and converts its argument to the object of constructors class. In this example, the conversion constructor is used to convert a string to an object of the newString type.
Note that the assignment operator is explicitly overloaded only for objects of newString type. However, the overloaded assignment operator also works if we want to store a character string into a newString object.
 
118. Consider the declaration
newString str;
and the statement
str = "Hello there";
	The compiler translates this statement into the statement
str.operator=("Hello there");
Now,
1.First the compiler automatically invokes the conversion constructor to create an object of newString type to temporarily store the string "Hello there".
2. Second the compiler invokes the overloaded assignment operator to assign the temporary newString object to object str. 
119. //Test Program
#include <iostream>
#include <cstring>
#include "myString.h"
using namespace std;
int main()
{
  newString s1 = "Sunny"; 	//initialize s1 using 
                               //the assignment operator 
  const newString s2("Warm"); //initialize s2 using 
                               //the conversion constructor
  newString s3;  //initialize s3 to null
  newString s4;  //initialize s4 to null
  cout<<"Line 1: "<<s1<<"    "<<s2<<"  ***"
	 <<s3 <<"###."<<endl; 			//Line 1
  if(s1 <= s2)     	     //compare s1 and s2; Line 2
	cout<<"Line 3: "<<s1<<" is less than "<<s2
 	    <<endl; 						//Line 3
  else							//Line 4
	cout<<"Line 5: "<<s2<<" is less than "<<s1
   	    <<endl; 						//Line 5
 
120.   cout<<"Line 6: Enter a string of length "
     <<"at least 7 --> ";				//Line 6
  cin>>s1;        				  //input s1; Line 7
  cout<<endl<<"Line 8: New value of s1 = "<<s1
 	<<endl;   	 					//Line 8
  s4 = s3 = "Birth Day";					//Line 9
  cout<<"Line 10: s3 = "<<s3<<", s4 = "<<s4<<endl;  	//Line 10
  s3 = s1;  						//Line 11
  cout<<"Line 12: The new value of s3 = "<<s3<<endl;	//Line 12
  s1 = "Bright Sky";  					//Line 13
  s3[1] = s1[5];						//Line 14
  cout<<"Line 15: After replacing the second character of s3 = "
      <<s3<<endl; 						//Line 15
  s3[2] = s2[3];				  		//Line 16
  cout<<"Line 17: After replacing the third character of s3 = "
      <<s3<<endl; 					 	//Line 17
  s3[5] = 'g'; 						//Line 18
  cout<<"Line 19: After replacing the sixth character of s3 = "
      <<s3<<endl; 					//Line 19
  return 0;
} 
121. Sample Run: In this sample run, the user input is in red.
Line 1: Hello    Happy  ***###.
Line 5: Sunny is less than Warm
Line 6: Enter a string of length at least 7 --> 123456789
Line 8: New value of s1 = 123456789
Line 10: s3 = Birth Day, s4 = Birth Day
Line 12: The new value of s3 = 123456789
Line 15: After replacing the second character of str3 = 1t3456789
Line 17: After replacing the third character of str3 = 1tW456789
Line 19: After replacing the sixth character of str3 = 1tW45g789
 
122. FUNCTION OVERLOADING
Overloading a function refers to several functions with the same name, but different parameters. The types of parameters determine which function to be executed. 
	int largerInt (int x, int y);
	char largerChar(char first, char second);
	double largerFloat(double u, double v);
	newString largerString(newString first, 	
						newString second);
	 
123. 
int larger(int x, int y);
char larger(char first, char second);
double larger(double u, double v);
newString larger(newString first, 
         		 newString second);
Function overloading is used when we have the same action for different sets of data. However, for function overloading to work, we must give the definition of each of the functions. 
124. TEMPLATES
By using templates we write a single code for a set of related functions- called function template and related classes- called class template. 
	The syntax for templates is:
	template <class Type>
 declaration;
	where Type is the type of the data and declaration is either a function declaration or a class declaration. 
In C++, template is a reserved word. 
The word class in the heading refers to any user-defined type or built in type. 
Type is referred as a formal parameter to the template.
Just as variables are parameters to functions, types (that is, data types) are parameters to templates. 
125. Function Templates
The syntax for function template is
	template <class Type>
	function definition;
	where Type is referred to as a formal parameter of the template and it is used to specify the type of the parameters to the function and the return type of the function, and to declare variables within the function. 
 
126. 	template <class Type>
	Type larger(Type x, Type y)
	{
   	if(x >= y)
		   return x;
   	else
		   return y;
	}
The statement
	cout<<larger(5,6)<<endl;
	is a call to the function template larger. 
Since 5 and 6 are of the type int, data type int is substituted for Type and the compiler generates the appropriate code.
In the function template definition if we omit the body of the function, the function template then, as usual, is the prototype. 
127. Example 16-8 
#include <iostream>
#include "myString.h"
using namespace std;
template <class Type>
Type larger(Type x, Type y);
int main()
{
	cout<<"Line 1: Larger of 5 and 6 = "
	    <<larger(5,6)<<endl;			//Line 1
	cout<<"Line 2: Larger of A and B = "
	    <<larger('A','B')<<endl;		//Line 2
	cout<<"Line 3: Larger of 5.6 and 3.2 = "
	    <<larger(5.6,3.2)<<endl;		//Line 3
	newString str1 = "Hello";			//Line 4
	newString str2 = "Happy";			//Line 5
	cout<<"Line 6: Larger of "<<str1<<" and "
	    <<str2<<" = "<<larger(str1, str2)
	    <<endl;					//Line 6
	return 0;
} 
128. 
template<class Type>
Type larger(Type x, Type y)
{
	if(x >= y)
	   return x;
	else
	   return y;
}
		
Output
Line 1: Larger of 5 and 6 = 6
Line 2: Larger of A and B = B
Line 3: Larger of 5.6 and 3.2 = 5.6
Line 6: Larger of Hello and Happy = Hello 
129. Class Templates
Like function templates, class templates are used to write a single code segment for a set of related classes. 
	Syntax:
	template<class Type>
	class declaration
Class templates are called parameterized types since based on the parameter type a specific class is generated. 
 
130. template <class elemType>
class listType
{
public:
    bool isEmpty();  
    bool isFull();  
    void search(const elemType& searchItem, bool& found); 
    void insert(const elemType& newElement); 
    void remove(const elemType& removeElement); 
    void destroyList();
    void printList();
    listType(); 
private:
    elemType list[100];  //array to hold the list elements
    int length;      	 //variable to store the number of 
     				 //elements in the list
}; 
131. The statement
 listType<int> intList; //Line 1
	declares intList to be a list of 100 components and each component is of the type int. 
The statement
 listType<newString> stringList; //Line 2
 	declares stringList to be a list of 100 components and each component is of the type newString. 
	
In the statements in Lines 1 and 2, listType<int> and listType<newString> are referred to as template instantiations or instantiations of the class template listType<elemType>, where elemType is the class parameter in the template header.  
132. A template instantiation can be created with either a built-in or user-defined type.
The function members of a class template are considered function templates. 
 
133. The definition of the member insert of the class listType is
template<class Type> 
void listType<Type>::insert(Type newElement)
{
  .
  .
  .
} 
In the heading of the member functions definition the name of the class is specified with the parameter Type. 
 
134. Header File and Implementation File of a Class Template
Until now, we have placed the definition of the class and the definition of the member functions in separate files. 
The object code was generated from the implementation file and linked with the user code. 
Passing parameters to a function has an effect at run time, whereas passing a parameter to a class template has an effect at compile time. 
Because the actual parameter to a class is specified in the client code, and because the compiler cannot instantiate a function template without the actual parameter to the template, we can no longer compile the implementation file independently of the client code. 
We could put the class definition and the definitions of the function templates directly in the client code, or we could put the class definition and the definitions of the function templates together in the same header file. 
Another alternative is to put the class definition and the definitions of the functions in separate files, but include a directive to the implementation file at the end of the header file. In either case, the function definitions and the client code are compiled together. 
We will put the class definition and the function definitions in the same header file.  
135. Example 16-9 
//Header file listType.h
#ifndef H_listType
#define H_listType
#include <iostream>
#include <cassert>
using namespace std;
template <class elemType>
class listType
{
public:
    bool isEmpty();
    bool isFull();
    int getLength();
    int getMaxSize();
    void sort(); 
    void print() const; 
    void insertAt(const elemType& item, int position);
    listType(int listSize = 50); 
    ~listType();  
136.   
private:
    int maxSize; //maximum number that can be 
    		     //stored in the list
    int length;  //number of elements in the list
    elemType *list; //pointer to the array that
 			  //holds the list elements
};
template<class elemType>
bool listType<elemType>::isEmpty()
{
	return (length == 0)
}
template<class elemType>
bool listType<elemType>::isFull()
{
	return (length == maxSize);
} 
137. template<class elemType>
int listType<elemType>::getLength()
{
	return length;
}
template<class elemType>
int listType<elemType>::getMaxSize()
{
	return maxSize;
}
   //constructor; the default array size is 50
template<class elemType>
listType<elemType>::listType(int listSize) 
{
	maxSize = listSize;
	length = 0;
	list = new elemType[maxSize];
}
 
138. template<class elemType>
listType<elemType>::~listType()  //destructor
{
	delete [] list;
}
template<class elemType>
void listType<elemType>::sort()   //selection sort
{
	int i, j;
	int min;
	elemType  temp;
	for(i = 0; i <length; i++)
	{
		min = i;
		for(j = i+1; j < length; ++j)
		   if(list[j] < list[min])
			min = j;
		temp = list[i];
		list[i] = list[min];
		list[min] = temp;
	}//end for
}//end sort 
139. template<class elemType>
void listType<elemType>::print() const
{
	int i;
	for(i = 0; i < length; ++i)
		cout<<list[i]<<"  ";
	cout<<endl;
}//end print
template<class elemType>
void listType<elemType>::insertAt
          (const elemType& item, int position)
{
	assert(position >= 0 && position < maxSize);
	list[position] = item;
	length++;
}
#endif  
 
140. //Program to test the class listType
#include <iostream>
#include "listType.h"
#include "myString.h"
using namespace std;
int main()
{
   listType<int> intList(100);			//Line 1
   listType<newString> stringList;		//Line 2
   int counter;						//Line 3
   int number;						//Line 4
   cout<<"List 5: Processing the integer List"
       <<endl;						//Line 5
   cout<<"List 6: Enter 5 integers: ";	//Line 6
										
   for(counter = 0; counter < 5; counter++)//Line 7
   {	
	cin>>number;					//Line 8
	intList.insertAt(number,counter);	//Line 9
   }
 
141.    cout<<endl;						//Line 10
   cout<<"List 11: The list you entered is: "; //Line 11
   intList.print();					//Line 12
   cout<<endl;						//Line 13
   cout<<"Line 14: After sorting, the list is: ";//Line 14
   intList.sort();					//Line 15
   intList.print();					//Line 16
   cout<<endl;						//Line 17
   newString str;					//Line 18
   cout<<"Line 19: Processing the string List"
       <<endl;						//Line 19
   cout<<"Line 20: Enter 5 strings: ";	//Line 20
   for(counter = 0; counter < 5; counter++)//Line 21
   {
	cin>>str;						//Line 22
	stringList.insertAt(str,counter);	//Line 23
   }
   cout<<endl;						//Line 24
   cout<<"Line 25: The list you entered is: "
       <<endl;						//Line 25
    
142.    stringList.print();				//Line 26
   cout<<endl;						//Line 27
   cout<<"Line 28: After sorting, the list is: "
       <<endl;						//Line 28
   stringList.sort();					//Line 29
   stringList.print();				//Line 30
   cout<<endl;						//Line 31	
   
   int intListSize;					//Line 32
   cout<<"Line 33: Enter the size of the integer "
       <<list: "; 					//Line 33
   cin>>intListSize;					//Line 34
   
   listType<int> intList2(intListSize);	//Line 35
   cout<<"Line 36: Processing the integer List"
       <<endl;						//Line 36
   cout<<"Line 37: Enter "<<intListSize
	 <<" integers: ";				//Line 37
    
143.    for(counter = 0; counter < intListSize; 
                     counter++)	//Line 38
   {
	cin>>number;					//Line 39
	intList2.insertAt(number,counter);	//Line 40
   }
   cout<<endl;						//Line 41
   cout<<"Line 42: The list you entered is: "<<endl;								//Line 42
   intList2.print();					//Line 43
   cout<<endl;						//Line 44
   cout<<"Line 45: After sorting, the list is: "
       <<endl;						//Line 45
   intList2.sort();					//Line 46
   intList2.print();					//Line 47
   cout<<endl;						//Line 48
   cout<<"Line 49: Length of the list = "
	 <<intList2.getLength()<<endl;		//Line 49
   cout<<"Line 50: Maximum size of the list = "
	 <<intList2.getMaxSize()<<endl;		//Line 50
   return 0;
} 
144. Sample Run: In this sample run, the use input is in red.
List 5: Processing the integer List
List 6: Enter 5 integers: 19 15 66 24 34
List 11: The list you entered is: 19  15  66  24  34
Line 14: After sorting, the list is: 15  19  24  34  66
Line 19: Processing the string List
Line 20: Enter 5 strings: summer cold winter warm sunny
Line 25: The list you entered is:
summer  cold  winter  warm  sunny
Line 28: After sorting, the list is:
cold  summer  sunny  warm  winter
Line 33: Enter the size of the integer list: 10
Line 36: Processing the integer List
Line 37: Enter 10 integers: 23 65 34 8 11 5 3 16 45 2
Line 42: The list you entered is:
23  65  34  8  11  5  3  16  45  2
Line 45: After sorting, the list is:
2  3  5  8  11  16  23  34  45  65
Line 49: Length of the list = 10
Line 50: Maximum size of the list = 10