OBJECT ORIENTED PROGRAMMING IN C++ �[UNIT-II]
U4.1
Learning Objectives
U4.2
There are three kind of access control specifiers:
Data Hiding
U4.3
#include <iostream.h>
class student
{
private:
int rollno;
char name[20];
void setdata(int rn, char* namein );
void outdata();
};
void main(){
student s1;
s1.setdata(1, “xx”); //can’t access
s1.outdata(); //can’t access
}
Program to Private Access
U4.4
Protected Members
Access control is similar to private members, has more significance in Inheritance.
U4.5
Protected Members Contd..
#include <iostream.h>
class student
{
protected:
int rollno;
char name[20];
void setdata(int rn, char *namein);
void outdata();
};
void main()
{
student s1;
s1.setdata(1, “xx”); //can’t access protected (same as private)
s1.outdata(); //can’t access
}
U4.6
Public Members Contd..
#include <iostream.h>
class student
{
public:
int rollno;
char name[20];
void setdata(int rn, char *namein);
void outdata();
};
void main()
{student s1;
s1.rollno; // can access public data
s1.setdata(1, “xx”); //can access public function
s1.outdata(); //can access public function
}
U4.7
EMPTY CLASSES / STUB
A class that has neither data nor code.
e.g; class xyz { };
class abc
{
};
At initial level of project, some of the classes are not fully identified or not fully implemented, hence they are implemented as empty class.
Important for Exception Handling.
U4.8
Passing Objects as Arguments
An object can be passed as an argument to a function by the following way
Returning Objects from functions:
Syntax is similar to that of returning variables
from function.
U4.9
#include<iostream.h>
class complex{private: float real, imag;
public: void getdata(); void outdata();
complex add (complex c2);};
complex complex:: add(complex c2)
{complex temp; temp.real = real + c2.real;
temp.imag = imag + c2. imag;
return temp;
} void main()
{complex c1, c2, c3;
c1.getdata(); c2.getdata();
c3 =c1.add(c2);
c1.outdata(); c2.outdata();
c3.outdata();}
Program
U4.10
Default Constructors
U4.11
Declaration and definition
Code fragment defines a constructor inside the class definition:
class X { int i;
public:
int j, int k;
X() { i=j=k=0; //constructor
}
};
The simple constructor X::X() is as an inline member function here.
U4.12
Declaration and definition
Code fragment can also be defined for a constructor outside the class definition:
class X { int i;
public:
int j, k;
X(); // only declaration as a prototype
: // other members
};
X ::X() //constructor defined outside
{ i = j = k = 0;
}
U4.13
Need for Constructors
A structure or an array in c++ can be initialized at the time of their declaration. For example;
struct student { int rollno;
float marks;
};
int main()
{student s1= {0, 0.0};
}
But such initialization does not work for a class because class members have their associated access specifier. They might not be available to the outside world (outside their class). The following code snippet is invalid in C++.
U4.14
class student { private:
int rollno;
float marks;
public:
: // public members
};
int main()
{ student senior = { 0, 0.0}; // illegal ! Data members are not accessible.
:
:
};
The private data members are inaccessibe by a non-member function in main().
Need for Constructors
U4.15
Need for Constructors
class student { private:
int rollno; float marks;
public:
void init()
{ rollno = 0; marks=0.0; }
: //other public members
};
int main()
{ student senior ; // create an object
senior. init(); // initialize it
:
}
U4.16
Need for Constructors
U4.17
Copy Constructor
U4.18
Destructors
Whenever an object is created within a program, it also needs to be destroyed.
If a class has constructor to initialize members, it should also have a destructor to free up the used memory.
A destructor, as the name suggest, destroys the values of the object created by the constructor when the object goes out of scope.
A destructor is also a member function whose name is the same name as that of a class, but is preceded by tilde (‘~`).
For example, the destructor of class salesperson will be ~salesperson().
A destructor does not take any arguments nor does it return any value. The compiler automatically calls them when the objects are destroyed.
U4.19
Copy Constructor
The copy constructor is, however, defined in the class as a parameterized constructor receiving an object as argument passed by reference.
U4.20
Program for Copy Constructor
U4.21
Copy Constructor
U4.22
Explanation
U4.23
Deep & Shallow Coping
U4.24
• A copy constructor is required to make a copy of the dynamically allocated memory.�• An overloaded assignment operator is required to make a copy of the dynamically allocated memory.
U4.25
#include <iostream.h>��void ConvertFToC(double f, double &c);�void ConvertFToC(float f, float &c);�void ConvertFToC(int f, int &c);�int main()
{� double df, dc;� float ff, fc;� int i_f,i_c; //if is a reserved word� df = 75.0;� ff = 75.0;� i_f = 75;
U4.26
// The compiler resolves the correct� // version of ConvertFToC based on � // the arguments in each call� cout << "Calling ""double"" version" << endl;� ConvertFToC(df,dc);� cout << df << " == " << dc << endl << endl;�� cout << "Calling ""float"" version" << endl;� ConvertFToC(ff,fc);� cout << ff << " == " << fc << endl << endl;�� cout << "Calling ""int"" version" << endl;� ConvertFToC(i_f,i_c);� cout << i_f << " == " << i_c << endl << endl;
}
U4.27
void ConvertFToC(double f, double &c)�{� cout << "In ""double"" version" << endl;� c = (f - 32.0) * 5. / 9.;�}��void ConvertFToC(float f, float &c)�{� cout << "In ""float"" version" << endl;� c = (f - 32.0) * 5. / 9.;�}�void ConvertFToC(int f, int &c)�{� cout << "In ""int"" version" << endl;� c = (f - 32) * 5. / 9.;�}
U4.28
Operator Overloading
U4.29
Overloadable Operators
Returntype operator operatorsymbol([arg1,[arg2]])
U4.30
U4.31
Binary Operator Over Loading
Returntype operator operatorsymbol (arg )
{
// body of operator function
}
U4.32
U4.33
Unary Operators
U4.34
Complement
U4.35
What is ‘Friend’
U4.36
class Cents
{
private: int m_nCents;
public:
Cents(int nCents) { m_nCents = nCents; }
// Overload -cCents
friend Cents operator-(const Cents &cCents);
};
// note: this function is not a member function!
Cents operator-(const Cents &cCents)
{ return Cents(-cCents.m_nCents);}
U4.37
constants. �Operator Use
= assignment
> boolean greater than < boolean less than
U4.38
Ternary Operator
U4.39
Unary Operator Overloading
// Program1.cpp: Index class with operator overloading for increment operator
#include < iostream.h>
class Index
{
private:
int value; // Index Value
public:
Index ( ) // No argument constructor
{
value = 0;
}
int GetIndex( ) // Index Access
{ return value;
}
void operator + +( ) // prefix or postfix increment operator
{
value = value + 1; // value+ + ;
}
} ;
U4.40
Unary Operator Overloading
void main( )
{ Index idx1, idx2; // idex1 and idx2 are objects of Index class
// display index values
cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;
cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;
// Advance Index objects with + + operators
+ + idx1; // equivalent to idx1. operator + + ( ) ;
idx2 + + ;
idx2 + + ;
cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;
cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;
}
RUN
Index1 = 0
Index2 = 0
Index1 = 1
Index2 = 2
U4.41
Unary operator using friend functions
Class test{
int x;
public:
test(){ x= 5;}
test(int a){ x= a;}
}
friend test operator++(test& ob);
};
test operator ++(test& ob) //passing an object by reference
{
ob.x++;
return (test(ob.x));};
U4.42
Example: Binary Operators
class BinaryExample
{
private:
int m_LocalInt;
public:
BinaryExample(int j)
{
m_LocalInt = j;
}
int operator+ (BinaryExample& rhsObj)
{
return (m_LocalInt + rhsObj.m_LocalInt);
}
};
U4.43
Example: Binary Operators (contd.)
void main()
{
BinaryExample object1(10), object2(20);
cout << object1 + object2; // overloaded operator called
}
U4.44
An operator function is created using the keyword operator. Operator functions can be either members or nonmembers of a class. Nonmember operator functions are almost always friend functions of the class.
A member operator function takes this general form:
ret-type class-name::operator#(arg-list)
{
// operations
}
U4.45
U4.46
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator+(loc op2);
};
// Overload + for loc.
loc loc::operator+(loc op2)
{
loc temp;
temp.longitude = op2.longitude + longitude;
temp.latitude = op2.latitude + latitude;
return temp;
}
int main()
{
loc ob1(10, 20), ob2( 5, 30);
ob1.show(); // displays 10 20
ob2.show(); // displays 5 30
ob1 = ob1 + ob2;
ob1.show(); // displays 15 50
return 0;
}
U4.47
operator+( ) has only one parameter even though it overloads the binary + operator. (You might expect two parameters corresponding to the two operands of a binary operator.) The reason that operator+( ) takes only one parameter is that the
operand on the left side of the + is passed implicitly to the function through the this pointer. The operand on the right is passed in the parameter op2.
The fact that the left operand is passed using this also implies one important point: When binary operators are overloaded, it is the object on the left that generates the call to the operator function.
ob1 = ob1 + ob2;
In order for the sum of ob1 and ob2 to be assigned to ob1, the outcome of that operation must be an object of type loc.
U4.48
It is important to understand that an operator function can return any type and that the type returned depends solely upon your specific application. It is just that, often, an operator function will return an object of the class upon which it operates.
EX-
class loc {
int longitude, latitude;
public:
loc() {} // needed to construct temporaries
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator+(loc op2);
loc operator-(loc op2);
loc operator=(loc op2);
loc operator++();
};
U4.49
// Overload + for loc.
loc loc::operator+(loc op2)
{
loc temp;
temp.longitude = op2.longitude + longitude;
temp.latitude = op2.latitude + latitude;
return temp;
}
// Overload - for loc.
loc loc::operator-(loc op2)
{
loc temp;
// notice order of operands
temp.longitude = longitude - op2.longitude;
temp.latitude = latitude - op2.latitude;
return temp;
}
U4.50
// Overload asignment for loc.
loc loc::operator=(loc op2)
{
longitude = op2.longitude;
latitude = op2.latitude;
return *this; // i.e., return object that generated call
}
// Overload prefix ++ for loc.
loc loc::operator++()
{
longitude++;
latitude++;
return *this;
}
U4.51
int main()
{
loc ob1(10, 20), ob2( 5, 30), ob3(90, 90);
ob1.show();
ob2.show();
++ob1;
ob1.show(); // displays 11 21
ob2 = ++ob1;
ob1.show(); // displays 12 22
ob2.show(); // displays 12 22
ob1 = ob2 = ob3; // multiple assignment
ob1.show(); // displays 90 90
ob2.show(); // displays 90 90
return 0;
}
U4.52
In C++, if the = is not overloaded, a default assignment operation is created automatically for any class you define. The default assignment is simply a member- by-member, bitwise copy. By overloading the =, you can define explicitly what the assignment does relative to a class. In this example, the overloaded = does exactly the same thing as the default, but in other situations, it could perform other operations. Notice that the
operator=( ) function returns *this, which is the object that generated the call. This arrangement is necessary if you want to be able to use multiple assignment operations such as this:
ob1 = ob2 = ob3; // multiple assignment
look at the definition of operator++( ). As you can see, it takes no parameters. Since ++ is a unary operator, its only operand is implicitly passed by using the this pointer.
U4.53
Overloading the Shorthand Operators You can overload any of C++'s "shorthand" operators, such as +=, –=, and the like.For example, this function overloads += relative to loc:
loc loc::operator+=(loc op2)
{
longitude = op2.longitude + longitude;
latitude = op2.latitude + latitude;
return *this;
}
When overloading one of these operators, keep in mind that you are simply combining an assignment with another type of operation.
U4.54
Operator Overloading Using a Friend Function
You can overload an operator for a class by using a nonmember function, which is usually a friend of the class. Since a friend function is not a member of the class, it does not have a this pointer. Therefore, an overloaded friend operator function is passed the operands explicitly. This means that a friend function that overloads a binary operator has two parameters, and a friend function that overloads a unary operator has one
parameter. When overloading a binary operator using a friend function, the left operand is passed in the first parameter and the right operand is passed in the second parameter.
U4.55
class loc {
int longitude, latitude;
public:
loc() {} // needed to construct temporaries
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
friend loc operator+(loc op1, loc op2); // now a friend
loc operator-(loc op2);
loc operator=(loc op2);
loc operator++();
};
U4.56
// Now, + is overloaded using friend function.
loc operator+(loc op1, loc op2)
{
loc temp;
temp.longitude = op1.longitude + op2.longitude;
temp.latitude = op1.latitude + op2.latitude;
return temp;
}
// Overload - for loc.
loc loc::operator-(loc op2)
{
loc temp;
// notice order of operands
temp.longitude = longitude - op2.longitude;
temp.latitude = latitude - op2.latitude;
return temp;
}
U4.57
// Overload assignment for loc.
loc loc::operator=(loc op2)
{
longitude = op2.longitude;
latitude = op2.latitude;
return *this; // i.e., return object that generated call
}
// Overload ++ for loc.
loc loc::operator++()
{
longitude++;
latitude++;
return *this;
}
U4.58
There are some restrictions that apply to friend operator functions. First, you may not overload the =, ( ), [ ], or –> operators by using a friend function. Second, as explained in the next section, when overloading the increment or decrement operators, you will need to use a reference parameter when using a friend function.
Using a Friend to Overload ++ or – –
If you want to use a friend function to overload the increment or decrement operators, you must pass the operand as a reference parameter. This is because friend functions do not have this pointers.
U4.59
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt;
}
void show() {
cout << longitude << " ";
cout << latitude << "\n";
}
loc operator=(loc op2);
friend loc operator++(loc &op);
friend loc operator--(loc &op);
};
// Overload assignment for loc.
loc loc::operator=(loc op2)
{
longitude = op2.longitude;
latitude = op2.latitude;
return *this; // i.e., return object that generated call
}
U4.60
// Now a friend; use a reference parameter.
loc operator++(loc &op)
{
op.longitude++;
op.latitude++;
return op;
}
// Make op-- a friend; use reference.
loc operator--(loc &op)
{
op.longitude--;
op.latitude--;
return op;
}
int main()
{
loc ob1(10, 20), ob2;
ob1.show();
++ob1;
ob1.show(); // displays 11 21
ob2 = ++ob1;
ob2.show(); // displays 12 22
--ob2;
ob2.show(); // displays 11 21
return 0;
}
U4.61
Binary Operator Overloading
c1 = x1 + i y1; c2 = x2 + i y2;
The operation c3 = c1 + c2 is given by
c3 = ( c1 .x1 + c2 .x2 ) + i ( c1. y1 + c2. y2 ) ;
# include < iostream.h>
class complex
{ private : float real ; float imag ;
public : complex ( ) // no argument constructor
{ real = imag = 0 . 0 ; }
U4.62
Binary Operator Overloading
void getdata ( ) // read complex number
{ cout << “Real Part ? “ ; cin >> real ;
cout << “Imag Part ? “ ; cin >> imag ; }
complex operator + ( complex c2 ) ;
void outdata ( char *msg )
{ cout << endl << msg ; cout << “ ( “ << real ;
cout << “ , “ << imag<<“ ) “ ; }} ;
complex complex : : operator + ( complex c2 )
{ complex temp ; // object temp of complex class
temp . real = real + c2 . real ; //add real parts
temp . imag = imag = c2 . imag ; //add imaginary parts
return ( temp ) ;}
U4.63
Binary Operator Overloading
void main ( )
{
complex c1, c2 , c3 ; // c1 , c2 , c3 are object of complex class
cout << “ Enter Complex Number c1 . . “ << endl ;
cl . getdata ( ) ;
cout << “ Enter Complex Number c2 . . “ << endl ;
c2 . getdata ( ) ;
c3 = c1 + c2 ; // add c1 and c2 and assign the result to c3 i.e; c3 = c1 . operator+ ( c2 ) ;
c3 . outdata ( “ c3 = c1 + c2 : “ ) ; // display result
}
RUN
Enter Complex Number c1 . .
Real Part ? 2.5
Imag Part ? 2.0
Enter Complex Number c2 . .
Real Part ? 3.0
Imag Part ? 1.5
C3 = c1 + c2 : ( 5 . 5 , 3.5 )
U4.64
Operator Returns Values�
The operator function in the previous program Program1.cpp has a subtle defect. An attempt to use an expression such as;
idx1= idx2++;
will lead to a compilation error like Improper Assignment because the return type of operator++ is defined as void type. Such an assignment operation can be permitted after modifying the return type of the operator ++() member function of the index class.
#include < iostream.h>
class Index
{ private: int value; // Index Value
public: Index ( ) // No argument constructor
{ value = 0;}
int GetIndex( ) { return value;}
U4.65
Operator Returns Values�
Index operator + +( ) // Returns nameless object of class Index
{ Index temp; // temp object
value = value + 1; // update index value
temp.value = value; // Initialise temp object
return temp; // Returns temp object
}} ;
void main( ){ Index idx1, idx2;
cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;
cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;
idx1 = idx2++; idx2 + + ; // Returned object of idx2++ is unused
cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;
cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;}
U4.66
Nameless Temporary Objects
A convenient way to return an object is to create a nameless object in the return statement itself.
#include < iostream.h>
class Index
{ private: int value; // Index Value
public: Index ( ) // No argument constructor
{ value = 0;}
int GetIndex( ) // Index Access
{ return value;}
Index operator + +( ) // Returns nameless object of class Index
{ value = value + 1; // update index value
return Index(value); }} ;
U4.67
Nameless Temporary Objects
void main( )
{ Index idx1, idx2; // idx1 and idx2 are objects of Index class
cout << “ \nIndex1 = “ << idx1 . GetIndex ( ) ;
cout << “ \nIndex2 = “ << idx2 . GetIndex ( ) ;
// Returned object of idx2+ + is assigned to idx1
idx1 = idx2++; // invokes the overloaded function and assigned the return value to the object idx1 of the index
idx2 + + ; // Returned object of idx2++ is unused
cout << “ \ nIndex1 = “ << idx1. GetIndex ( ) ;
cout << “ \ nIndex2 = “ << idx2. GetIndex ( ) ;
}
U4.68
Need For Virtual Functions�
When objects of different class in a class hierarchy, react to the same message in their own unique ways, they are said to exhibit polymorphic behavior. In C++, a pointer to the base class can be used to point to its derived class objects.
#include<iostream.h> #include<string.h>
class Father // Father’s name
{ char name[20]; public:
Father(char *fname)
{strcpy(name, fname); }
void show() //show in base class
{cout<<”Father’s name:” << name << endl; }};
class son: public Father{ char name[20]; // Son’s name
public: void show(){}};
U4.69
Postfix Increment and Decrement Operators: ++ and –
i++;
U4.70
expre_Postfix_Increment_and_Decrement_Operators.cpp
#include <iostream>
using namespace std;
int main() {
int i = 10;
cout << i++ << endl;
cout << i << endl;
}
U4.71
In the postfix form, the increment or decrement takes place after the value is used in expression evaluation, so the value of the expression is the same as the value of the operand. For example, the following program prints "++i = 6":
#include <iostream>
using namespace std;
int main() {
int i = 5;
cout << "++i = " << ++i << endl;
}
U4.72
Conclusion
U4.73
Summary
U4.74
Summary
U4.75
Review Questions [Objective Types]
delete a;
delete [ ]a;
4. How can we initialize a const data members?
U4.76
Review Questions [Objective Types]
U4.77
Review Questions [Short Answer Types]
U4.78
Review Questions [Short Answer Types]
U4.79
Review Questions [Long Answer Types]
1. Write a program using a class to store marks list of 15 students and to print the highest marks as well as the average of all marks.
U4.80
Review Questions [Long Answer Types]
U4.81
Review Questions [Long Answer Types]
U4.82
Recommended Books
TEXT:
1. A..R.Venugopal, Rajkumar, T. Ravishanker “Mastering C++”, TMH, 2009.
2. S. B. Lippman & J. Lajoie, “C++ Primer”, 6th Edition, Addison Wesley, 2006.
REFERENCE:
1. R. Lafore, “Object Oriented Programming using C++”, Galgotia Publications, 2008.
2. D . Parasons, “Object Oriented Programming with C++”, BPB Publication.
3. Steven C. Lawlor, “The Art of Programming Computer Science with C++”, Vikas Publication.
4. Schildt Herbert, “C++: The Complete Reference”, 7th Ed., Tata McGraw Hill, 2008.
U4.83