OOPSCPP Module 3
OOPSCPP Module 3
OOPSCPP Module 3
Overloading of Operators:
Operators like arithmetic and comparison can be done directly on numeric data types. But they cannot be
applied on programmer defined data types such as classes and structures. One way to do this is given below.
Here the class Point has two variables x and y as coordinates of a point.
Eg:
#include<iostream>
using namespace std;
class Point
{
int x,y;
public:
Point(int a=0, int b=0) { x=a; y=b; } // constructor
void setPoint(int a, int b) { x=a; y=b; }
int getX() { return x; }
int getY() { return y; }
void showPoint() { cout<< "(" << x << ", " << y << ")"; }
};
int main()
{
Point p1(2,3), p2(5,8), p3;
p1.showPoint(); cout<<endl; // shows (2,3)
p2.showPoint(); cout<<endl; // shows (5,8)
p3.setPoint(p1.getX()+p2.getX(), p1.getY()+p2.getY()); //set the resultant point
p3.showPoint(); // shows (7,11)
cout<<endl;
return 0;
}
Another way is to define functions which accepts the operands as parameters and returns the resultant object.
Point addPoints(Point p, Point q)
{ Point r;
int rx, ry;
rx=p.getX()+q.getX();
ry=p.getY()+q.getY();
r.setPoint(rx,ry);
return r;
}
Thus the addition can be done by the function call p3=addPoints(p1,p2).
But it will be nice if we can do the addition as p3 = p1 + p2 just like the addition of two numeric values. This
can be done by overloading the operator +. This can be done by simply changing the above function header
by a special type of function header, ie using the keyword operator.
Point operator + (Point p, Point q)
{ Point r;
int rx, ry;
rx=p.getX()+q.getX();
ry=p.getY()+q.getY();
r.setPoint(rx,ry);
return r;
}
Friend Functions
One of the important concept of C++ is data hiding, i.e., a nonmember function cannot access an object's
private or protected data. But, sometimes this restriction may force programmer to write long and complex
codes. So, there is mechanism built in C++ programming to access private or protected data from non-member
function which is friend function and friend class.
If a function is defined as a friend function then, the private and protected data of class can be accessed from
that function. The complier knows a given function is a friend function by its keyword friend. The declaration
of friend function should be made inside the body of class (can be anywhere inside class either in private or
public section) starting with keyword friend.
class class_name
{
...... .... ........
friend return_type function_name(arguments);
...... .... ........
}
Now, we can define friend function of that name and that function can access the private and protected data of
that function. The keyword 'friend' is not used in function definition of the friend function. A friend function
can be either a global function or a member function of another class. Inside it, the object variables can be
directly accessed using dot operator.
class Point
{
int x,y;
public:
Point(int a=0, int b=0) { x=a; y=b; }
Friend Class: A class can be made a friend of another class using keyword friend. For example:
class B; // declare class B before use
class A{
friend class B; // class B is a friend class
..... ..... .....
};
class B{
..... ..... .....
};
When a class is made a friend class, all the member functions of that class becomes friend function. In this
program, all member functions of class B will be friend function of class A. Thus, any member function of
class B can access the private and protected data of class A. But, member functions of class A cannot access
the private and protected data of class B.
Operator Overloading for Nonnumeric Classes And Overloading the Assignment Operator
In most of the programmer-defined classes, operator overloading can be done and the objects can be used in
the same way as built-in types. The overloading works simply in numeric classes, but there are nonnumeric
elements such as character arrays (strings) where the overloading needs extra care. To avoid memory leakage
and memory overflow, the strings are allocated memory dynamically. Thus the overloading function will be
more complex.
Eg: a String class with ‘=’ and ‘+=’ operators overloaded.
#include<iostream>
#include<cstring>
#include<cstdlib>
public:
String(const char *s) // constructor
{ len=strlen(s);
str=new char(len+1);
if(str==NULL) { cout<<"Memory allocation failed!!!\n"; exit(1); }
strcpy(str,s);
cout<<"String object created - "<<str<<endl;
}
String() // constructor
{ len=0;
str=new char(len+1);
};
int main()
{
String s1("good"), s2("morning"), s3;
s1+=s2; cout<<"s1: "<<s1.show()<<endl;
s3=s1; cout<<"s3: "<<s3.show()<<endl;
return 0;
}
Another way to do it is to use a member initialization list that calls the constructor of the class components. In
this example, the member initialization list calls a Point constructor to initialize Point components of class
Rectangle.
Eg:
class Rectangle
{
Point p1,p2;
int borderWidth;
public:
Rectangle (Point& pt1, Point& pt2, int width):p1(pt1), p2(pt2) //member initialization list
{ borderWidth = width; } // give values to built-in components
...
};
int main()
{
Point pt1(11,22), pt2(33,44);
Rectangle r2(pt1,pt2,5);
}
There is another way for initialising the components; using the components' Default Constructors. When an
object of class Rectangle is created, events take place in the following order:
1. The data member p1 of class Point is created, its x and y are allocated, then its constructor is called.
2. The data member p2 of class Point is created, its x and y are allocated, then its constructor is called.
3. The data member borderWidth of type int is created.
4. The body of the Rectangle class constructor is executed.
When a composite object is destroyed, the process of memory management and function calls is reversed. The
composite class destructor is called first, before any memory is deallocated. When the destructor terminates,
the data members are destroyed in the order opposite to the order of their creation.
Reference Data Members: The data members can be references. These references can point to the objects
outside of the composite object. All references in C++ are constants. They cannot change after they are
initialized. Hence, reference data members (similar to constant data members) must be initialized only in a
member initialization list: No initialization in the body of the constructor is allowed.
#include<iostream>
using namespace std;
class Point // component class
{
int x,y;
public:
Point(int a=0, int b=0)
{x=a; y=b; cout<<"Contructor of Point called...(" << x << ", " << y << ")\n"; }
void showPoint() { cout<< "(" << x << ", " << y << ")"; }
void setPoint(int a, int b) {x=a; y=b; }
};
Using Objects as Data Members of Their Own Class: Whan we define a class, the same class object can be
used as a data member inside the class, but these data members must be references or pointers.
Eg:
class Point {
int x, y;
Point &anchor;
public:
Point (int a=0, int b=0)
{ x = a; y = b; }
};
Container Classes
Container classes are a special case of composite classes, which are useful when the application needs a data
type that contains a dynamic collection of values. Almost any application needs one or more container classes
created by others. Often the application needs a container or a collection class that can contain a variable
number of objects. Usually, a container object is initially empty and has no components. While the application
is executing, the component objects become available and are added to the container for temporary storage or
for processing.
There are many different kinds of container classes (such as arrays, lists, trees, stack, queue, etc.), each of
which has various advantages, disadvantages, and restrictions in their use. By far the most commonly used
container in programming is the array. Unlike built-in arrays, array container classes generally provide
dynamic resizing (when elements are added or removed), remember their size when they are passed to
functions, and do bounds-checking. This not only makes array container classes more convenient than normal
arrays, but safer too.
Container classes typically implement a fairly standardized minimal set of functionality. Most well-defined
containers will include functions that:
• Create an empty container (via a constructor)
• Insert a new object into the container
• Remove an object from the container
• Report the number of objects currently in the container
• Empty the container of all objects
• Provide access to the stored objects
• Sort the elements (optional)
Container classes are designed to perform these operations on behalf of the client code. The client code
requests the container to add a component, find a component, and access each component in the collection;
and the container object performs these operations, insulating the client code from the low-level details. As a
result, responsibility is pushed down from the client code to the server code (container class).
Eg:
class Shape
{ private: ...
protected: ...
public: ...
};
class Rectangle: public Shape //Rectangle is a subclass of Shape
{ private: ...
protected: ...
public: ...
};
Member How Members of the Base Class Appear in the Derived Class
Access
Specifier
Private Private members of the base class are inaccessible to the derived class.
Protected members of the base class become private members of the derived class.
Public members of the base class become private members of the derived class.
Protected Private members of the base class are inaccessible to the derived class.
Protected members of the base class become protected members of the derived class.
Public members of the base class become protected members of the derived class.
Public Private members of the base class are inaccessible to the derived class.
Protected members of the base class become protected members of the derived class.
Public members of the base class become public members of the derived class.
In principle, a derived class inherits every member of a base class except constructor and destructor. It means
private members are also become members of derived class. But they are inaccessible by the members of
derived class.
Eg:
class Shape
{
protected:
float width, height;
public:
void setData (float a, float b) { width = a; height = b; }
void showValues( ) { cout<<”Shape values: “<<width<<”, “<<height<<endl; }
};
int main ()
{
Rectangle rect;
Triangle tri;
rect.setData (5,3); // function of base class
tri.setData (2,5);
cout << rect.area() << endl; // function of derived class Rectangle
cout << tri.area() << endl; // function of derived class Triangle
return 0;
}
A derived class inherits all base class methods with the following exceptions:
• Constructors, destructors and copy constructors of the base class.
Types of Inheritance
Hybrid Inheritance
class A { .. };
class B: public A { .. };
class C: public A { .. };
class D: public B, protected C { .. };