Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Object Oriented Prog.

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 45

Object Oriented Programming through C++

Object Oriented Programming through C++

What is Object Oriented Programming?

A type of programming in which programmers define not only the data type of a data structure, but
also the types of operations (functions) that can be applied to the data structure. In this way, the data structure
becomes an object that includes both data and functions.
Object Oriented Programming treats data as a critical element and does not allow to flow freely
around the system. It ties data more closely to the functions that operate on it and protects it from
unintentional modification by other functions. OOP allows us to decompose a problem into a number of
entities called Objects and then build data and functions around those entities. Combinations of data and
functions make up an object.

The data of an object can be accessed only by the


member functions associated with that object. However, function function
member functions of one object can access the member
functions of another objects. Some of the features of
object-oriented paradigm are:
data
1. Emphasis on data rather than procedure.
2. Programs are divided into objects. function function
3. Member functions that operate on the data of an
object are tied together.
4. Data is hidden and can’t be accessed by external
functions. Object = Data + Functions
5. Objects may communicate with each other
through member functions.
6. New data and member functions can be easily added whenever necessary.

Moreover, Object-Oriented Programming is an approach that provides a way of modularizing


programs by creating partitioned memory area for both data and functions that can be accessed as
templates for creating copies of such modules on demand.

C++ is an object oriented language, It was developed by Bjarne Stroustrup at AT & T Bell Laboratories in
USA, in the early 1980. C++ is a superset of C.

Classes and Objects

A class may be thought of as a ‘data type’ and an object as a ‘variable’ of that type. Once a class has
been defined, we can create any number of objects belonging to that class. Each object is associated with
the data of type class with which they are created. A class is thus a collection of objects of similar type. A
class is a group of objects that share common properties and relationships. Class declaration defines a new
type that links code and data. It binds the data and its associated functions together. It allows the data to be
hidden from external use. For example, mango, apple and orange are the members of class fruit. Classes
are user-defined data types and behave like the built-in types of a programming language.
A class specification has 2 parts
1. Class declaration,
2. Class function definitions.

1
Object Oriented Programming through C++

The class declaration describes the type and scope of its members. The class function definition
describes how the class functions are implemented.

An example of a class is
Class ABC
{
private:
int x,y;
public:
void getdata(int a, int b);
void setdata( );
};
The variables of a class is called ‘data members’ and the functions are called ‘member functions’. In the
above example, x and y are the data members and getdata( ) and setdata( ) are the member functions.
The class members that have declared as private can be accessed only from within the class, and public
members can be accessed from outside of the class. By default, the data and functions declared within a class
are private to that class.
There are 3 access specifiers in OOP: private, public and protected( needed in inheritance purposes).
An object has physical existence. An object is an instance of a class. It is an identifiable entity with some
characteristics and behavior. To declare an object first we have to write the class name and then the object
name. Thus an object is created. It can access the entire properties of a class.
For example, ABC ob;
Here ob is the object of class ABC.
Member functions are accessed from the outside of the class by ‘.’ Operator. Such as ob.setdata( ) and
ob.getdata(1, 2).

Differences between Procedural Programming and Object Oriented Programming

Procedural Programming Object-Oriented Programming


1.Programs are divided into simpler programs called 1.Programs are divided into objects.
functions.
2. Data are moved freely around the system form 2.OOP treats data as a critical element in the program
function to function. and does not allow it to flow freely around the
system.
3. Data are not secured here, they can be accessed 3. Data and functions are binds together to keep
from anywhere. protect from the outside interference or misuse.
4. Data can be accessed by external functions. 4. Data cannot be accessed by external functions.
5. New data are added at the beginning of the 5. New data can be easily added whenever necessary.
program.
6. Doesn’t have the ability to simulate real-world 6. Have the ability to simulate real-world event much
event. more effectively
7. Employs a top-down approach. 7. Employs a bottom-up approach.

Encapsulation and Data Abstraction

Encapsulation is a mechanism in which data and functions of a class are binds together to keep protect
from the outside interference or misuse.. It is the most striking feature of a class. When the data and functions
of a class are binds together, then an object is created of that class. The data are not accessed by the outside
world, and only those function which are wrapped in the class can access it. These functions provide the
interface between the object’s data and program. The insulation of the data from direct access by the program
is called data hiding or information hiding.

2
Object Oriented Programming through C++

Abstraction refers to the act of representing essential features without including the background details or
explanations. Classes use the concept of abstraction and are defined as a list of abstract attributes such as size,
weight and cost, and methods that operate on these attributes. They encapsulate all the essential properties of
the objects that are to be created.

 Abstract data type or ADT

Abstract refers to the act of representing essential features without including the background details or
explanations. Classes use the concept of abstraction and are defined as a list of abstract attributes – data
members and member functions.
Since the classes use the concept of data abstraction, they are known as Abstract Data Types(ADT).

 Reusability

Once a class has been created and debugged, it can be distributed to other programmers for use in their
own programs. This is called reusability. In OOP, the concept of inheritance provides an important extension
to the idea of reusability. A programmer can take an existing class and then add some additional features and
capabilities to the class without modifying the class. Then the new class then have the combined features of
both the classes.

 Const Member Function

A const member function guarantees that it will never modify any of its class’s member data
A const member function is declared as
<return type> function_name( parameter _list) const
{
//body of the function
}
When a member function declared as const, then the compiler checks if you have made any change of any
data members of that class. Compiler will generate an error if such functions try to change the data values.
Same meaning can be applied on data members by simply declare the data members like as

const int a=5;

 Scope Resolution Operator

‘::’ is a scope-resolution operator. This operator links a class name with a member name. The operator tells
the compiler in what class the member belongs to. A member is defined by the scope resolution operator as

return_type classname :: function_name(parameter_list)


{
//body of the func
}

Constructor & Destructor

A constructor is used to initiate an object automatically when it is declared. A constructor is called when
an object comes into existence. A constructor is executed when the object declaration statement is
encountered. A constructor is declared as

3
Object Oriented Programming through C++

class name
{
public:
name( )
{
//body of constructor
};
};

[ Note: Constructors of global objects are executed before the execution of the main function].
constructors can be called in any one of two ways:
name ob1=name(100); //explicit call
name ob1(100);//implicit call

A destructor is called when an object is destroyed. A destructor never takes any argument; it does not
return any value. It will be invoked automatically by the complier upon exist from program. A destructor is
declared as:
class name
{
public:
~name()
{
// body of destructor
}
}

 Implicit Constructor

This constructor creates objects, even though was not defined in the class. This constructor will not do
anything and is defined just to satisfy the compiler.

class integer
{
Public:
integer( ) { } // implicit integer
}

 Properties of constructors

1. They should be declared in the public section.


2. They are invoked automatically when the objects are created.
3. They do not have return types, not even void and therefore, and they cannot return values.
4. They cannot be inherited, though a derived class can call the base class constructor.
5. The constructors that can not have any parameter are known as default constructor.
6. Constructors cannot be virtual.
7. We can’t refer their addresses.
8. An object with a constructor( or destructor) cannot be used as a member of union).
9. They make ‘implicit calls’ to the operators new and delete when memory allocation is required.
class_name objectname(data);
class_name objectname=class_name(data);

4
Object Oriented Programming through C++

 Differences between Constructor and Destructor

1. A constructor is a member function, which is invoked automatically when an object is created and a
Destructor is a member function, which is invoked when an object is destroyed.
2. A constructor sometimes takes argument. But a destructor never takes any argument.

 Similarity between Constructors and Destructors


1. They don’t have any return types
 Advantages of Destructors

1. Destructors are used to destroy object that have been created by a constructor.
2. They are used to release the memory space for future use when they are no longer required.

 Differences between Structures and Classes


1. The members of a structure are by default private whereas the members of a class are by default
public.
2. Structures do not permit data hiding. Members of structures can be directly accessed from the outside
unlike classes.

Local Class

The class that is defined within main function or another general function is called local class.

 Disadvantages of local classes


1. The member functions of the local class must defined within the class.
2. Local classes cannot use global variable or functions.
3. Local classes cannot access the variables of the functions in which the class has been declared.
4. It can not use static variables.

Reference Variables
A reference variable provides an alias for previously defined variables. For example, if we make the
variable sum and a reference to the variable total, then sum and total can be used interchangeably to represent
that variable.
int sum=10;
int &total=sum;

 Differences between pointers and references


1. We cannot obtain the address of a reference.
2. We cannot create arrays of reference
3. Reference creates the alias of variables and pointer takes the address of a variable
4. References used in copy constructors.

 Prototype Declaration
The prototype describes the function to interface to the compiler by giving details such as the
number and type of arguments and the type of return values.
Function prototype is a declaration statement in the calling function. It is declared by writing
the signature of a function followed by a semicolon (;), that is if a signature of a function is
void(int a, float b), then the prototype declaration of that function is
void(int a, float b);

5
Object Oriented Programming through C++

The argument list of the function prototype must be same as the argument list in the function
calling.

Static Variable and Static member functions

 Some properties of static variable


1. It is initialized to zero when the first object of its class is created. No other initializes is
permitted.
2. Only one copy of that member is created for the entire class and is shared by all the objects
of that class, no matter how many objects are created.
3. It is visible only within the class, but its lifetime is the entire program.

 Properties of static member function


1. A static function can have access to only other static members( functions or variables)
declared in the same class.
2. A static member function can be called using the class name(instead of its objects) as
follows:
Class_name::function_name;

 Example of static variable and static member function

#include<iostream.h>
class gamma
{
static int total;
public:
gamma() Output:
{
total ++;
Total is 1
}
~gamma() Total is 3
{ Destroying
total--; Destroying
cout<<"Destroying "<<endl; Destroying
}
static void showtotal()
{
cout<<"Total is
"<<total<<endl;
}
};

int gamma::total=0; //defining total


int main()
{
gamma g1;
gamma :: showtotal();
gamma g2, g3;
gamma::showtotal();
return 0;
}

6
Object Oriented Programming through C++

 Restrictions on static member functions:


1. Static member functions can use only static data.
2. Global member functions and data can be accessed by static member functions.
3. There can not a static and non-static versions of the same functions.
4. This can not have a this pointer.
5. Static member functions may not be virtual.
6. They may not be declared as const or volatile.

Friend Function
Friend function is a nonmember function of any class. Friend functions are used to access
all protected and private members of a class. To declare a friend function the keyword friend is
written followed by the ‘signature of the function’. A Friend function can not be declared within
a class. It is always declared outside of the class without using scope resolution operator. To call
a friend function outside of the class, it doesn’t need the dot operator. Friend function can act as
a bridge between two classes. A friend function can handle the private members of more than
one class.

//Sum of two private members of two classes using friend functions

#include<iostream.h>
class c2; //forward declaration
class c1
{
public:
friend int sum(c1 a, c2 b);
int c;
};

class c2
{
public:
friend int sum(c1 a, c2 b);
int d;
}

int sum(c1 a, c2 b)
{
return( a.c + b.d);
}

void main()
{
c1 ob1; c2 ob2;
ob1.c=10;
ob2.d=20;
cout<<sum(ob1,ob2);
}

7
Object Oriented Programming through C++

 Advantages of Friend functions


1. To overload an operator between more than one class, friend function is used.
2. Using friend function one can access the private or protected members of a function.

 Disadvantages of Friend functions:


1. A derived class cannot inherit a friend functions of its base class.
2. Friend functions may not have a storage class_specifier. It may not be declared as static or extern.
3. Data security does not holds any more.

This pointer
When the member functions are called then they are automatically passed to an implicit argument
that is a pointer to the invoking object. This pointer is called this pointer.
This pointer is useful to show that the member that it points to is the member of the invoking
object or classes. That is
this->b=base (b=base)
this->b refers to the object’s copy of b.

This pointer is also useful when operators are overloaded and whenever a member functions must
utilize a pointer to the object that invoked it.

 Disadvantages of this pointer


1. As friend functions are not the members of any classes then this pointers are not passed through a
friend function.
2. Static member functions do not have a this pointer.

 Disadvantage of pointers
1. By a base class pointer one cannot access elements of a derived class.
2. A pointer of any class type cannot points to any other objects of any type.

 Differences between new and malloc()

1. New operator automatically allocates enough memory to hold an object of the specified type. We do
not need to use an size of operator. Because the size is automatically computes.
2. New operators automatically return the pointer to the specified type. We don’t need to use an explicit
type cast as you we do while allocating memory with malloc( ).
3. New and delete operators can be overloaded.
4. It is possible to initialize the object while creating the memory space.

Inline functions

An Inline function is a function that is expanded in line when it is invoked. That is, the compiler
replaces the function call with the corresponding function code. To make a function inline add the ‘inline’
keyword before declaring a function.

inline int func(int a) // inline functions


{
return a*a;
}

8
Object Oriented Programming through C++

But there are some restrictions on defining a function to be inline functions. A function declared to be
inline functions must have one or two lines. Inline keywords merely send a request, not a command to the
compiler. The compiler may ignore the request if the inline function has too long lines to compile.

A simple program to illustrate a inline function

#include<iostream.h>
inline int func(int a)
{
return a*a;

}
void main()
{

cout<<func(5);
}
Inline functions are used to save memory space, which is suitable when a function is to be called many
times. These functions are useful to run a program faster. As ordinary functions it does not require to
saving register, push current status on to stack.

[ Note: In case of a class, if the member functions are declared inside the class then the member functions
are called inline function]

 Disadvantages of inline functions


1. If a function has a loop or a switch or goto exists, then these functions are not work as inline.
2. Inline functions must not contain a static variable.
3. Inline functions are not recursive.

 Differences between macros and inline


1. Macros are applicable in data items. Inline functions are applicable in functions.
2. In macros error checking does not occur during compilation unlike inline functions.

Default arguments

C++ allows us to call a function without specifying all its arguments. In such cases, the function assigns a
default value to the parameter which does not have a matching arguments in the function call. Default
values are specified when the function prototype is declared. The compiler looks at the prototype to see
how many arguments a function uses and alerts the program for possible default values. Here is an
example of a prototype with default values.
float amount( float a, int b, float c=0.0)
The above prototype declares a default value of 0.0 to the argument rate.
A function call like
value=amount(5000,7) passes a=5000, b=7 and c=0.0
If a function call like value=amount(2000, 3, 0.12) then passes a=2000, b=3, c=0.12

One important point is that only the trailing argument can have default values. We must add default
values from right to left that is
int func(int i, int j=10, int k=10) // is legal

int func(int j=2, int k) // is illegal

9
Object Oriented Programming through C++

The program illustrates the use of default argument

#include<iostream.h>
void line(char ch='*', int size=25);

void main()
{

line('=',20);
line('=');
line();
}

void line(char ch, int size)


{
for(int i=0; i<size;i++)
cout<<ch;
cout<<endl;
}

Output:

====================
=========================
*************************

 Advantages of default arguments

1. We can use default arguments to add new parameters to the existing functions.
2. Default arguments can be used to combine similar functions into one.

How an objects are passed as an function arguments?

Like any other data type objects are also passed as an function argument. These can be done in
two ways.
1. Pass-by-value
2. Pass-by-reference

In the first method, a copy of an entire object is passed to a function. Since a copy of the object is
passed to the function any changes made to the object inside the function do not affect the object by
which the function was called.
void item:: getdata(item t1)
{
int count;
t1.a=count++;
}

Here t1 is an object of type item. T1 is passed in the function argument as call-by-value.

10
Object Oriented Programming through C++

In the second method, the address of an object is passed to a function. This means that any changes made
to the object inside the function will reflect the actual object. These method is more efficient since it
passed only the address of the object and not the entire object.

void item::getdata(item &t1)


{
Int count;
t1.a=count++;
}

Here, the address of the object t1 is passed to the function argument as call-by-reference.

INHERITANCE
I nheritance is the process in which the objects of one class can access the properties of another class.
In Object Oriented Programming, heritance provides the concept of reusability. This means, that we can add
additional features to an existing class without modifying it. This is possible by deriving a new class form the
existing class. Then the existing class called the base class and the new class is called derived or child class.
The new class will have the combined features of both the two classes. A class can also inherits properties
from more than one class or form more than one level. A derived class with only one base class is called
single inheritance and with several base classes is called multiple inheritance.

A derived class can be defined by specifying its relationship with the base class by specifying its
relationship with the base class in additon to its own details. The general form of defining a derived class is:

Class derived-classname : visibility_mode base_classname


{
// body of the derived class
};

The visibility-mode can be private, public or protected. This is optional. Default visibility-mode is
private. Visibility-mode specifies whether the features of the base class are privately derived or publicly
derived or protectedly derived.

For example, If XYZ is a base class and ABC is a derived class of XYZ

Class ABC: private XYZ // privately derived


{
//body of the class
};

Class ABC: public XYZ // publicly derived


{
//body of the class
};

Class ABC: protected XYZ // protectedly derived


{
//body of the class

11
Object Oriented Programming through C++

};

When the base class is privately inherited by a derived class, ‘public’ members of the base class
become ‘private’ members of the derived class, so the public members of the base class can be accessed by
the member functions of the derived class, but they are not accessible by the objects of the derived class.
Protected members of the base class become ‘private’ members of the derived class.

When the base class is publicly inherited by a derived class, ‘public’ members of the base class
become ‘public’ members of the derived class, so they are accessible by the objects of the derived class.
Private members of the base class can not be inherited and they are not accessible by the objects of the
derived classes. ‘Protected’ members of a base class become ‘protected’ members of the derived class.

When the base class is inherited by a derived class as protected , ‘public’ members of the base class
become ‘protected’ members of the derived class, ‘protected’ members of the base class become ‘protected’
members of the derived class and ‘private’ members of the base class are not accessible by the objects of the
derived classes.

For example, as illustrated in this program, objects of type derived can directly access the public
members of base:

#include<iostream.h>

class base
{
int i,j;

public:
void set(int a, int b) {i=a; j=b;}

void show() { cout<<i<<" " <<j<<"\n";}


};

class derived: public base


{
int k;
public:
derived(int x){ k=x;}

void showk() {cout<<k<<"\n";}


};

int main()
{
derived ob(3);
ob.set(1,5); // access member of base
ob.show(); // access member of base
ob.showk(); // uses member of derived class
}

When the base class is inherited by using the private access specifier, all public and protected members of
the base class become private members of the derived class. For example, the following program will not
even complile because both set( ) and show( ) are now private elements of derived.

12
Object Oriented Programming through C++

//This program won't compile


#include<iostream.h>

class base
{
int i,j;
public:
void set(int a, int b) { i=a; j=b; }

void show(){ cout<<i<<" "<<j<<"\n";}


};

// Public elements of base are private in derived


class derived:private base
{
int k;
public:
derived(int x) { k=x;}
void showk() {cout<<k<<"\n";}
};

int main()
{
derived ob(3);
ob.set(1,2); //error, can't access set()
ob.show();//error, can;t access show()

return 0;
}

 Inheritance and Protected Members

The protected keyword is included in C++ to provide greater flexibility in the inheritance mechanism. When
a member of a class is declared as protected, that member is not accessible by other, nonmember elements of
the program. Access to a protected member is the same as access to private member-it can be accessed only
by other members of its class. The sole exception to this is when a protected member is inherited. In this case,
a protected member differs substantially from a private one.

By using protected, one can create class members that are private to their class but that can still be
inherited and accessed by a derived class. Here is an example:

#include<iostream.h>

class base
{
protected:
int i,j; // private to base, but accessible by derived
public:
void set(int a, int b) { i=a; j=b;}
void show() { cout<<i<<" "<<j<<"\n";}
};

class derived:public base


{

13
Object Oriented Programming through C++

int k;
public:
//derived may access base's i and j
void setk() { k=i*j;}
void showk() { cout<<k<<"\n";}
};

int main(void)
{
derived ob;
ob.set(2,3); //OK, known to derived
ob.show(); //OK, known to derived
ob.setk();
ob.showk();
return 0;
}

In this example, because base is inherited by derived as public, and because i and j are declared as
protected, derived’s function setk() may access them. If I and j had been declared as private by base, then
derived would not have access to them, and the program would not compile .

When a derived class is used as a base class for another derived class, any protected member of
the initial base class that is inherited(as public) by the first derived class may also be inherited as
protected again by a second derived class. For example, this program is correct, and derived2
does indeed have access to i and j.
#include<iostream.h>

class base
{
protected:
int i,j;
public:
void set(int a, int b) { i=a; j=b;}
void show() { cout<<i<<" "<<j<<"\n";}
};

// i and j inherited as protected.


class derived1 : public base
{
int k;
public:
void setk() { k=i*j;} //legal
void showk() { cout<<k<<"\n";}
};

// i and j inherited indirectly through derived1


class derived2 : public derived1
{
int m;
public:
void setm() { m=i-j;} //legal
void showm() { cout<<m<<"\n";}
};

14
Object Oriented Programming through C++

int main(void)
{
derived1 ob1; derived2 ob2;
ob1.set(2,3); ob1.show();
ob1.setk(); ob1.showk();

ob2.set(3,4); ob2.show();
ob2.setk(); ob2.showk();
ob2.setm(); ob2.showm();
}

 Protected Base-Class Inheritance

It is possible to inherit a base class as protected. When this is done, all public and protected members of
the base class become protected members of the derived class. For example,

#include<iostream.h>

class base
{
protected:
int i,j;//private to base, but accessible by derived
public:
void setij(int a, int b) { i=a, j=b;}
void showij() { cout<<i<<" "<<j<<"\n";}
};

//Inherit base class as protected


class derived:protected base
{
int k;
public:
//derived may access base's i and j and setij()
void setk() { setij(10,12); k=i*j;}

//may access showij()here


void showall()
{
cout<<k<<" " ;
showij();
}
};

int main(void)
{
derived ob;
//ob.setij(2,3) // illegal, setij() is protected member of derived
ob.setk(); //OK, public member of derived

15
Object Oriented Programming through C++

ob.showall(); // PK. public member of derived


//ob.showij(); // illegal, showij() is protected member of derived
return 0;
}

 Inheriting Multiple Base Classes

// An example of multiple base classes


#include<iostream.h>

class base1
{
protected:
int x;
public:
void showx() { cout<<x<<"\n"; }
};

class base2
{
protected:
int y;
public:
void showy() { cout<<y<<"\n";}
};

// Inherit multiple base classes


class derived:public base1, public base2
{
public:
void set(int i, int j) { x=i, y=j;}
};

int main(void)
{
derived ob;
ob.set(10,20);//provided by derived
ob.showx(); ob.showy();

}
 Constructors & Destructors in Inheritance

When an object of a derived class is created, then first the base’s constructor is called and then the
derived’s constructor is called. When that object is destroyed, then first the derived’s destructor is called
and then the base’s destructor is called. That means, constructors are executed in their order of derivation.
Destructors are executed in reverse order of derivation .

#include<iostream.h>
class base
{
public:
base() { cout<<"Constructing base\n"; }

16
Object Oriented Programming through C++

~base() { cout<<"Destructing base\n";}


};

class derived : public base


{
public:
derived() { cout<<"Constructing derived\n"; }
~derived() { cout<<"Destructing derived\n"; }
};

int main(void)
{
derived ob;
return 0;
}

Output:
Constructing base
Constructing derived
Destructing derived
Destructing base
 Why protected access specifiers are used in Inheritance?

We know that private member functions of a base class cannot be inherited by the derived class,
therefore they are not accessed by the member functions of the derived class. But if we need to inherit the
private members of the base class, then we must inherit the base class protectedly. These modify the
visibility limit of the private member by making it public. A member declared as protected is accessible
by the member functions within its class and any class that are derived from it. It cannot be accessed by
the functions outside of these two classes. When a protected member is inherited in public mode then it
becomes protected, so it can accessed by the member functions of the derived class. When a protected
member is inherited in private mode then it becomes private in the derived class.
When a base class is inherited by its derived class in protected mode then the public and protected
members of base class becomes protected members of derived class, and the private members of the base
class cannot accessible by the derived class.
To inherit a base class in protected mode we declare:
class D: protected B
{
// body of the class
};

 In what order are the class constructors called when a derived class object is created?

When a derived class object is created then the class constructors are called in the order in which they
appear in the declaration of the derived class. When a object of a derived class is created then first the
constructors in the base class are called and then the constructors in the derived class are called. The

17
Object Oriented Programming through C++

constructor of the derived class receives the entire list of values as its arguments and passes them on to
the base constructors in order in which they are declared in the derived class.

The derived class constructor contains two parts separated by a colon(:). The first part contains the
declaration of the arguments that are passed to derived constructor and the second part contains the
initialization of the objects of the base class and derived class.
Here is a simple program
class alpha
{
int a;
public:
alpha(int m){ a=m; }
void showa() {cout<<a; }
};

class beta : public alpha


{
int b;
public:
beta(int c, int d) : alpha(c), b(d){}
void showb(){ cout<<b; }
};

int main(void)
{
beta ob(5,10);
ob.showa();
ob.showb();
return 0;
}

 How do we pass arguments to a constructor in a base class?

We pass arguments to a constructor on a base class, with the help of the derived class that inherits the
base class. A derived class constructor takes all arguments of its own and the arguments of the base class
constructor. And then pass these arguments to one or more base-class constructor. The general form of this
expanded derived class constructor is shown here:-

derived-constructor(arg_list): base1(arg_list), base2(arg_list)……baseN(arg_list)


{
// body of the derived-class constructor
}
Here, base1 through baseN are the names of the base classes inherited by the derived class. Notice
that a colon separates that derived class constructor declaration from the base-class specifications, and that
base-class specifications are separated form each other by commas, in the case of multiple base classes.
Consider this program:

#include<iostream.h>
class base
{
protected:
int i;

18
Object Oriented Programming through C++

public:
base(int x) { i=x; cout<<"Constructing base\n";}
~base( ) { cout<< "Destructing base\n";}
};

class derived : public base


{
int j;
public:
//derived uses x; y is passed to base.
derived(int x, int y): base(y)
{
j=x; cout<<"Constructing derived\n";
}
~derived( ) { cout<<"Destructing derived\n";}
void show( ) { cout<<i<<" "<<j<<"\n"; }
};

int main()
{
derived ob(3,4);
ob.show(); //displays 4 3
return 0;
}
Output :
Constructing base
Constructing derived
4 3
Destructing derived
Destructing base

Here, derived’s constructor is declared as taking two parameters, x and y. However, derived( ) uses only x; y
is passed along to base( ). In general, the derived class’ constructor must declare both the parameters that it
requires as well as any required by the base class.

Here is an example that uses multiple base classes:

#include<iostream.h>
class base1
{
protected:
int i;
public:
base1(int x) { i=x; cout<<"Constructing base1\n";}
~base1( ) { cout<< "Destructing base1\n";}
};

class base2
{
protected:
int k;
public:
base2(int x) { k=x; cout<<"Constructing base2\n";}
~base2( ) { cout<< "Destructing base2\n";}

19
Object Oriented Programming through C++

};

class derived : public base1, public base2


{
int j;
public:

derived(int x, int y, int z): base1(y), base2(z)


{
j=x; cout<<"Constructing derived\n";
}
~derived( ) { cout<<"Destructing derived\n";}
void show( ) { cout<<i<<" "<<j<<" " <<k<<"\n"; }
};

int main()
{
derived ob(3,4,5);
ob.show(); //displays 4 3 5
return 0;
}

Output :

Constructing base1
Constructing base2
Constructing derived
4 3 5
Destructing derived
Destructing base2
Destructing base1

It is important to understand that arguments to a base-class constructor are passed via arguments to
the derived class’ constructor. Therefore, even if a derived class’ constructor does not use any arguments, it
will still need to declare one if the base class requires it. In this situation, the arguments to the derived class
are simply passed along to the base. For example, in this program, the derived class’ constructor takes no
arguments, but base1( ) and base2( ) do.

#include<iostream.h>
class base1
{
protected:
int i;
public:
base1(int x) { i=x; cout<<"Constructing base1\n";}
~base1( ) { cout<< "Destructing base1\n";}
};

class base2
{
protected:
int k;
public:
base2(int x) { k=x; cout<<"Constructing base2\n";}
~base2( ) { cout<< "Destructing base2\n";}
};

20
Object Oriented Programming through C++

class derived : public base1, public base2


{
int j;
public:
/* Derived constructor uses no parameter, but still must be declared as
taking them to pass them along to base classes*/
derived(int y, int z): base1(y), base2(z)
{
cout<<"Constructing derived\n";
}
~derived( ) { cout<<"Destructing derived\n";}
void show( ) { cout<<i<<" " <<k<<"\n"; }
};

int main()
{
derived ob(3,4);
ob.show(); //displays 3 4
return 0;
}

Output:

Constructing base1
Constructing base2
Constructing derived
3 4
Destructing derived
Destructing base2
Destructing base1

Polymorphism
OOP languages support polymorphism, which is characterized by the phrase “one interface,
multiple methods”. Polymorphism is the attribute that allows one interface to control access to a general class
of actions. The specific action selected is determined by the exact nature of a situation. Polymorphism helps
reduce complexity by allowing the same interface to be used to access a general class of actions.

Polymorphism

Compile time Run time


Polymorphism Polymorphism

Function Operator
Overloading Overloading Virtual
Function

When the appropriate member function could be selected while the program is running, is known as run
time polymorphism. C++ supports virtual functions to achieve runtime polymorphism.

21
Object Oriented Programming through C++

At run time, when it is known what class objects are under consideration, then the appropriate
version of the function is invoked. Since, the function is linked with a particular class much later after the
compilation, this process is called late binding. It is also known as dynamic binding because the selection
of the appropriate function is done dynamically at runtime.
 Function Overloading

Function Overloading is the process of using the same name for two or more functions. The secret
to overloading is that each redefinition of the function must use either different types of parameters or
a different number of parameters. It is only through these differences that the compiler knows which
function to call in any given situation. For example, this program overloads myfunc( ) by using
different types of parameters

#include<iostream.h>
int myfunc(int i); Here, in the main program
double myfunc(double i); when the function
int main() myfunc(10 is called then the
{ compiler invokes
cout<<myfunc(10);//calls myfunc(int i) automatically the function
cout<<myfunc(5.4); //calls myfunc(double i) int myfunc(int i), because 10
return 0;
}
is a integer type argument
and the parameter in the
double myfunc(double i) function definition is also an
{ integer type.
return i;
}

int myfunc(int i)
{
return i;
}

The next program overloads myfunc( ) using a different number of parameters


#include<iostream.h>
int myfunc(int i);
int myfunc(int i, int y); Here, in the main
int main() program when the
{ function myfunc(10) is
cout<<myfunc(10)<<"\n";//calls myfunc(int i) called then the compiler
cout<<myfunc(4, 8); //calls myfunc(int i, int y) invokes automatically
return 0; the function int
} myfunc(int i) because
int myfunc(int i)
{ the no. of arguments in
return i; the function matches
} with the calling function.
int myfunc(int i, int j)
{
return i*j;
}
 Function Overriding

22
Object Oriented Programming through C++

Function Overriding is the mechanism of having the same member function in both the base class and
derived classes. In this case, the function in the derived class overrides on the function of the base
class.

#include<iostream.h>
class Base
{ Output:
public: Derived class
void show()
{ In this case, the base class and
cout<<"Base class"; the derived class both contains
} the same member functions
}; void show( ). In the main
function an object is created of
class Derv : public Base the type Derv. Then the
{
public:
member function show( ) is
void show() called by the object d1. In this
{ case, the compiler invoked the
cout<<"Derived class"; function of derived class. If we
} want to call the show( )
}; function of base class then we
have to write.
int main(void)
{ D1.Base::show();
Derv d1;
d1.show();return 0;
}

 Copy constructor

A copy constructor is a constructor that creates a new object and copies its argument into it. The
default copy constructor which is provided automatically by the compiler for every object, perform a
member-by-member copy. This is similar to what the assignment operator does; the difference is that the copy
constructor also creates a new object.

23
Object Oriented Programming through C++

#include<iostream.h>
class alpha
{
private:
int data;
public:
alpha()
{
}
alpha(int d)
{
data=d;
}
alpha(alpha &a)
{
data=a.data;
cout<<"\n Copy constructor invoked";
}
void display()
{
cout<<data;
}
void operator=(alpha &a)
{
data=a.data;
cout<<"Assignment operator invoked";
}
};

int main(void)
{
alpha a1(37);
alpha a2;
a2=a1; //invoke = operator
cout<<"\n a2= "; a2.display();
alpha a3(a1); // invoke copy constructor
a3.display();
}

If we use alpha (alpha a), then the compiler complains that is out of memory. Because when an argument is
passed by value, a copy of it is constructor. But this is the copy constructor, so it calls itself. In fact, it calls
itself over and over until the complier runs out of memory. So, in the copy constructor, the argument must be
passed by reference, which creates no copy.

 Differences between copy constructor and assignment operator

Copy constructor is called every time a copy of an object is made. When you pass an object by value,
either into a function or as a function's return value, a temporary copy of that object is made.

Assignment operator is called whenever you assign to an object. Assignment operator must check to see if the
right-hand side of theassignment operator is the object itself. It executes only the two sides are not equal.

24
Object Oriented Programming through C++

Operator Overloading

C++ has the ability to provide the operators with a special meaning for a data type. The mechanism
of giving such special meanings to an operator is known as operator overloading. To define an additional
task to an operator, we must specify what it means in relation to the class to which the operator is applied.
This is done with the help of special function, called operator function. The operator function defines the
operations performed by the overloaded operator relative to the class upon which it will work.

The general form of an operator function is:


returntype classname :: operator # (arg_list)
{
// Function body
}

The # is a placeholder. When a operator functions is to be created substitute the operator for the #. For
example, if you overloading the ‘ /’ operator, then use operator ‘/’. When you are overloading a unary
operator, arg_list will be empty. When you are overloading binary operators, arg_list will contain one
parameter.

Here is an example of operator overloading. This program creates a class called counter which stores
the count value. It overloads the ++ operator relative to this class.
// overloading unary operator
#include<iostream.h>
class counter
{
private:
int count;
public:
counter(): count(0)
{ }
counter(int c): count (c)
{ }
void display()
{
cout<<count<<"\n";
}
void operator ++()
{
++count;
}
};
int main(void)
{
counter c1(10);
++c1; ++c1; // prefix operators
c1.display(); return 0;
}

In this program, an object c1 of class type counter is created, we increment c1 twice and then displaying the
resulting value.

25
Object Oriented Programming through C++

If we write the operator function as;

void operator ++(int)


{
++count;
}

Then the ++ operator is treated as postfix operators and then we have to write the expression c1++ instead of
++c1.

Here is an another example of operator overloading which overload binary operator ‘+’.
#include<iostream.h>
class sum
{
int data;
public:
sum()
{
data=0;
}
sum(int a)
{
data=a;
}
void display()
{
cout<<data;
}
sum operator + (sum s2)
{
sum temp;
temp.data=s2.data+data;
return temp;
}
};

int main(void)
{
sum ob1(5), ob2(8);
ob1=ob1+ob2;
ob1.display(); // displays 13
return 0;
}

In this program two objects are created. Then we add the two object using ‘+’ operator then assigns
the result to the ob1.

 Disadvantages
1. We can not alter the precedence of an operator.
2. We cannot change the no. of operands that an operator takes.
3. Operator function cannot have default arguments.
4. . :: ? operators cannot be overloaded.

26
Object Oriented Programming through C++

[ Note: A friend function will have only one argument for unary operation and two for binary operation,
where as a member function has no argument for unary operation and one operator for binary operations]

#include<iostream.h>
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);
loc operator -(loc op2);
loc operator =(loc op2);
loc operator++();

};
//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;
temp.longitude=op2.longitude-longitude;
temp.latitude=op2.latitude-latitude;
return temp;
}

//overload = for loc


loc loc :: operator =(loc op2)
{
longitude=op2.longitude;
latitude=op2.latitude;
return *this; // return that object which generates the call
}

//overload ++ operator
loc loc :: operator ++()
{
longitude++;

27
Object Oriented Programming through C++

latitude++;
return *this;
}
int main(void)
{
loc ob1(10, 20), ob2(5, 30), ob3(90,90);
++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;
}

// operator overloading using string


#include<iostream.h>
#include<string.h>
const int MAX=80;
class string
{
char str[MAX];
public:
string()
{
strcpy(str, " ");
}
string( char *s)
{
strcpy(str,s);
};
void show()
{
cout<<str<<endl;
}
string operator + (string ss)
{
if (strlen(str) +strlen(ss.str)<MAX)
strcat(str, ss.str);
else
cout<<"String too long";
return (str); // return *this
}
};

int main(void)
{
string s1="object";
string s2=" oriented";
string s3;
s3=s1+s2; // s1=s1+s2; or s1+s2
s3.show(); // s1.show();

28
Object Oriented Programming through C++

return 0;
}

// operator overloading using bool operator


#include<iostream.h>
#include<string.h>
const int MAX=80;
class string
{
char str[MAX];
public:
string()
{
strcpy(str, " ");
}
string( char *s)
{
strcpy(str,s);
};
void show()
{
cout<<str<<endl;
}

bool operator = (string ss)


{
return(strcmp(str, ss.str)==0)? true: false;
}

bool operator < (string ss)


{
if (strcmp(str, ss.str)<0)
return true;
else
return false ;
}
};

int main(void)
{
string s1="abc";
string s2="abcd";
string s3="abc";
if( s1< s2)
cout<<"s2 is larger";
else
cout<<"s1 is larger";
if(s1=s3)
cout<<"strings are equal";
else
cout<<"strings are not equal`";
return 0;
}

// overload '<' operator to compare two distances

29
Object Oriented Programming through C++

#include<iostream.h>
class Distance
{
int feet;
float inches;
public:
Distance()
{
feet=0;
inches=0.0;
}

Distance(int ft, float in)


{
feet=ft;
inches=in;
}
bool Distance :: operator < (Distance d2)
{
float df1= feet +inches/12;
float df2=d2.feet +(d2.inches/12);
return (df1<df2)? true:false;
}
};
int main(void)
{
Distance d1(13, 4.5);
Distance d2(14, 12.1);
if(d1<d2)
cout<<"Dist1 is greater\n";
else
cout<<"Dist2 is greater\n";
return 0;
}

 Operator overloading using friend functions

One can overload an operator for a class by using 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 passes 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.
In this program, the operator+ ( ) function is made into a friend.

30
Object Oriented Programming through C++

#include<iostream.h>
class loc
{
int longitude, latitude;
public:
loc() { }
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

};

// now + is overloaded using frined fucntion


loc operator + (loc op1, loc op2)
{
loc temp;
temp.longitude=op1.longitude+op2.longitude;
temp.latitude=op1.latitude+op2.latitude;
return temp;
}
int main(void)
{
loc ob1(10, 20), ob2(5, 30);
ob1=ob1+ob2;
ob1.show();
return 0;
}

Assume some class that defines a member operator+( ) function that adds an object of the class to an integer.
Given an object of that class called Ob, the following expression is valid:

Ob + 100 //valid

In this case, Ob generates the call to the overloaded + function, and the addition is performed. But what
happens if the expression is written like this?

100 + Ob // invalid

In this case, it is an integer that appears on the left. Since an integer is a built-in type, no operation
between an integer and an object of Ob’s type is defined. Therefore, the compiler will not compile this

31
Object Oriented Programming through C++

expression. The solution to the preceding problem is to overload addition using a friend, not a member
function. When this is done, both arguments are explicitly passed to the operator function. Therefore, to allow
both object +integer and integer +object, simply overload the function twice-one version for each situation.
Thus, when you overload an operator by using two friend functions, the object may appear on either the left
or right side of the operator.

This program illustrates how friend functions are used to define an operation that involves an object
and built-in type:

#include<iostream.h>

class number
{
int num;

public:
number()
{ }

number(int a)
{
num=a;
}

void show()
{
cout<<"Value is " <<num<<endl;
}
friend number operator+ (number ob, int val);
friend number operator+ (int val, number ob);

};

number operator+ (number ob, int val)


{
number temp;
temp.num=ob.num+val;
return temp;
}

number operator+ (int val, number ob)


{
number temp;
temp.num=ob.num+val;
return temp;
}

int main(void)
{
number ob1(5), ob2(10), ob3, ob4;
ob3=ob1+14;
ob4=20+ob2;
ob1.show(); // displays 5
ob2.show(); // displays 10
ob3.show(); // displays 19
ob4.show(); // displays 30

32
Object Oriented Programming through C++

return 0;
}

Virtual Functions
A virtual function is a member function that is declared within a base class and redefined by a derived
class. To create a virtual function, precede the function’s declaration in the base class with the keyword
virtual. When a class containing a virtual function is inherited, the derived class redefines the virtual function
to fit its own needs. In essence, virtual functions implement the “one interface, multiple methods” philosophy
that underlies polymorphism. The virtual within the base defines the form of the interface to that function.
Each redefinition of the virtual function by a derived class implements its operation as it relates specifically to
the derived class. That is, the redefinition creates a specific method.
A base-class pointer can be used to point to an object of any class derived from the base. When a base
pointer to a derived object that contains a virtual function, C++ determines which version of that function to
call based upon the type of object pointed to by the pointer. And this determination is made at runtime. Thus,
when different objects are pointed to, different versions of the virtual function are executed.
#include<iostream.h>
class base
{
public:
virtual void vfunc( ){
cout<<"This is base's vfunc()\n";
}
};

class derived1: public base


{
public:
void vfunc( ){
cout<<"This is derived1's vfunc()\n";
}
};

class derived2: public base


{
public:
void vfunc( ){
cout<<"This is derived2's vfunc()\n";
}
};

int main(void)
{
base *p ,b;
derived1 d1;
derived2 d2;

// point to base
p=&b;
p->vfunc( ); //access base's vfunc()

// point to derived1
p=&d1;
p->vfunc( ); //access derived1's vfunc()

33
Object Oriented Programming through C++

// point to derived2
p=&d2;
p->vfunc( ); //access derived2's vfunc()

Output:
This is base's vfunc()
This is derived1's vfunc()
This is derived2's vfunc()

As the program illustrates, inside base, the virtual function vfunc( ) is declared. Notice that the
keyword virtual precedes the rest of the function declaration. When vfunc( ) is redefined by derived1 and
derived2, the keyword virtual is not needed.

In this program, base is inherited by both derived1 and derived2. Inside each class definition, vfunc(
) is redefined relative to that class. Inside main( ), four variables are declared:

Next, p is assigned the address of b, and vfunc( ) is called via p. Since p is pointing to an object of
type base, that version of vfunc( ) is executed. Next, p is set to the address of d1, and again vfunc( ) is called
by using p. This time p points to an object of type derived1. This causes derived1’s vfunc( ) to be executed.
Finally, p is assigned the address of d2, and p->vfunc( ) causes the version of vfunc( ) redefined inside
derived2 to be executed. The key point here is that the kind of object to which p points determines which
version of vfunc( ) is executed. Further, this determination is made at run time, and this process forms the
basis for run-time polymorphism.

However, this is not the case, and the term overloading is not applied to virtual function redefinition
because several differences exist. Perhaps the most important is that the prototype for a redefined virtual
function must match exactly the prototype specified in the base class. This differs from overloading a normal
function, in which return types and the member and type of parameters may differ. Another important
restriction is that virtual functions must be nonstatic members of the classes of which they are part. They
cannot be friends.

 The Virtual Attribute Is Inherited

When a virtual function is inherited, its virtual nature is also inherited. This means that when a derived
class that has inherited a virtual function is itself used as a base class for another derived class, the virtual
function can still be overridden. Put differently, no matter how many times a virtual function is inherited,
it remains virtual. For example, consider this program:
#include<iostream.h>
class base
{
public:
virtual void vfunc( ){
cout<<"This is base's vfunc()\n";
}
};

class derived1: public base


{
public:
void vfunc( ){

34
Object Oriented Programming through C++

cout<<"This is derived1's vfunc()\n";


}
};

/* derived2 inherits virtual function vfunc() from derived1. */


class derived2: public derived1
{
public:
void vfunc( ) // vfunc() is still virtual
{
cout<<"This is derived2's vfunc()\n";
}
};

int main(void)
{
base *p ,b;
derived1 d1;
derived2 d2;

// point to base
p=&b;
p->vfunc( ); //access base's vfunc()

// point to derived1
p=&d1;
p->vfunc( ); //access derived1's vfunc()

// point to derived2
p=&d2;
p->vfunc( ); //access derived2's vfunc()

Ouput of the program is same as the previous output.

 Virtual Functions Are Hierarchical

When a function is declared as virtual by a base class, a derived class may override it.
However, the function does not have to be overridden. When a derived class fails to override a
virtual function, then when an object of that derived class accesses that function, the function
defined by the base class is used. For example, consider this program in which derived2 does not
override vfunc( ):

#include<iostream.h>
class base
{
public:
virtual void vfunc( )
{
cout<<"This is base's vfunc()\n";
}
};

class derived1: public base

35
Object Oriented Programming through C++

{
public:
void vfunc( )
{
cout<<"This is derived1's vfunc()\n";
}
};

class derived2: public base


{
public:
// vfunc() is not overridden by derived2, base's is used
};

int main(void)
{
base *p ,b;
derived1 d1;
derived2 d2;

// point to base
p=&b;
p->vfunc( ); //access base's vfunc()

// point to derived1
p=&d1;
p->vfunc( ); //access derived1's vfunc()

// point to derived2
p=&d2;
p->vfunc( ); //access derived2's vfunc()

Output:
This is base's vfunc()
This is derived1's vfunc()
This is base's vfunc()

Because derived2 does not override vfunc( ), the function defined by base is used when vfunc( ) is
referenced relative to objects of type derived2.

Pure Virtual Functions

When a virtual function is not redefined by a derived class, the version defined in the base class will
be used. However, in many situations there can be no meaningful definition of a virtual function
within in a base class. For example, a base class may be not be able to define an object sufficiently to
allow a base-class virtual function to be created. Further, in some situations you will want to ensure
that all derived classes override a virtual function. To handle, these two cases, C++ supports the pure
virtual function.

36
Object Oriented Programming through C++

A pure virtual function is a virtual function that has no definition within the base class. To
declare a pure virtual function, we use the general form:

virtual type func_name(parameter_list)=0;

When a virtual function is made pure, any derived class must provide its own definition. If
the derived class fails to override the pure virtual function, a compile-time error will result.

#include<iostream.h>
class area
{
protected:
int x, y;
public:
area(int a, int b=1)
{
x=a, y=b;
}

virtual void show() =0;


};

class rectangle : public area


{
public:
rectangle(int a, int b):area(a,b)
{ }

void show()
{
cout<<"Area of rectangle is "<<x*y<<"\n";
}
};

class square: public area


{
public:
square(int a): area(a)
{
}

void show()
{
cout<<"Area of square is "<<x*x<<"\n";
}
};
int main(void)
{
rectangle r1(3,8);square s1(5);
r1.show();
s1.show();
return 0;
}
Output:
Area of rectangle is 24

37
Object Oriented Programming through C++

Area of square is 25

Here the base class area, contains x and y, the constructor and a pure virtual function show( ). The derived classes
rectangle and square inherit x and y and redefine show() to fit its own needs.

Virtual Destructor
Base class destructor should always be virtual. Suppose you use delete with a base class pointer to a
derived class object to destroy the derived-class object. If the base-class destructor is not virtual then delete,
like a normal member function, calls the destructor for the base class, not the destructor of the derived class.
This will cause only the base part of the object to be destroyed.
#include< iostream.h>
class Base
{
public:
~Base( ) // non-virtual destructor
// Virtual ~Base( ) // virtual destructor
{
cout<<”Base Destroyed\n”;
}
};
class Derv : public Base
{
public:
~Derv( )
{
cout<<”Derv Destroyed\n”;
}
};

int main()
{
Base *pBase=new Derv; delete pBase;
}

Output: Base Destroyed


This shows that the destructor for the Derv part of the object is not called. When you make the Base
destructor as virtual then the output is
Derv destroyed
Base destroyed
Now both parts of the derived class object are destroyed properly. To ensure that derived-class
objects are destroyed properly, you should make destructors in all base classes virtual.

 Abstract Classes

A class that contains at least one pure virtual function is said to be abstract. Because an abstract class
contains one or more functions for which there is no definition (that is, pure virtual function), no objects of an
abstract class may be created. But, we can create pointers to an abstract class. This allows abstract classes to
support the run-time polymorphism.

Virtual Base Classes

An element of ambiguity can be introduced into a C++ program when multiple base classes are
inherited. For example, consider this incorrect program:-

38
Object Oriented Programming through C++

// This program contains an error and will not compile……


#include<iostream.h>
class base
{
public:
int i;
}; base
// derived1 inherits base
class derived1 : public base
{ Derived1 Derived2
public:
int j;
};
Derived3
// derived2 inherits base
class derived2 : public base
{
public: Fig. Diamond Structure Problem
int k;
};

/* derived3 inherits both derived1 and derived2. This means that there are two
copies of base in derived3!*/
class derived3 : public derived1, public derived2
{
public:
int sum;
};

int main()
{
derived3 ob;
ob.i=10; // This is ambiguous, which i???
ob.j=20;
ob.k=30;

// i is ambiguous, too
ob.sum=ob.i+ob.j+ob.k;

// also ambiguous, which i?


cout<<ob.i<<" "<<ob.j<<" "<<ob.k<<" "<<ob.sum<<"\n";
}

As the comments in the program indicate, both derived1 and derived2 inherit base. However, derived3
inherits both derived1 and derived2. This means that there are two copies of base present in an object of type
derived3. Therefore, in an expression like ob.i = 10;
Which i is being referred to, the one in derived1 or the one in derived2? Because there are two
copies of base present in object ob, there are two ob.i! So, the statement is ambiguous.
So, there is a problem. And there is a solution of the above problem. When two or more objects are
derived from a common base class, we can prevent multiple copies of the base class by declaring the base
class as virtual when it is inherited. You accomplish this by preceding the base class’ name with the keyword
virtual when it is inherited. ( For example, here is another version of the example program in which derived3
contains only one copy of base:

39
Object Oriented Programming through C++

// This program uses virtual base classes


#include<iostream.h>
class base
{

public:
int i;
};

// derived1 inherits base as virtual


class derived1 : virtual public base
{
public:
int j;
};

// derived2 inherits base as virtual


class derived2 : virtual public base
{
public:
int k;
};

/* derived3 inherits both derived1 and derived2.


This time, there is only one copy of base class */
class derived3 : public derived1, public derived2
{

public:
int sum;
};

int main()
{
derived3 ob;
ob.i=10; // now unambiguous
ob.j=20;
ob.k=30;

// unambiguous
ob.sum=ob.i+ob.j+ob.k;

// unambiguous
cout<<ob.i<<" "<<ob.j<<" "<<ob.k<<" "<<ob.sum<<"\n";
}

Now, that both derived1 and derived2 have inherited base as virtual, any multiple inheritance involving
them will cause only one copy of base to be present. Therefore, in derived3 there is only one copy of
base and
ob.i = 10 is perfectly valid and unambiguous and in this case this base class is called ‘virtual base class’.

Early vs. Late Binding

40
Object Oriented Programming through C++

Early Binding refers to events that occur at compile time. In essence, early binding occurs when all
information needed to call a function is known at compile time. Examples of early binding include normal
function calls(including standard library functions), overloaded function calls, and overloaded operators. The
main advantage to early binding is efficiency. Because all information necessary to call a function is
determined at compile time, these types of function calls are very fast.

The opposite of early binding is late binding. As it relates to C++, late binding refers to function calls
that are not resolved until runtime. Virtual functions are used to achieve late binding. When an object is
accessed via a base pointer or reference, the virtual function actually called is determined by the type of
object pointed to by the pointer. Because in most cases this cannot be determined at compile time, the objects
and the functions are not linked until run time. The main advantage to late binding is flexibility. Late binding
can make slower execution times because a function call is not resolved until runtime.

Templates
A generic function or a template function defines a general set of operations that will be applied to various
types of data. The type of data that the function will operate upon is passed to it as a parameter. A single
general procedure can be applied to a wide range of data. By using generic functions we can apply sorting
algorithm to an array of integers or an array of floats.

A generic function is created using the keyword template. The general form of a template function
definition is shown here:

template<class Ttype> ret-type func-name(parameter list)


{
//body of function
}

Here, Ttype is a placeholder name for a data type used by the function. It is only a placeholder that the
compiler will automatically replace with an actual data type when it creates a specific version of the function.

The following example creates a generic function that swaps the values of the two variables with
which it is called. The general process of exchanging two values is independent on the type of the variables.

#include<iostream.h>

//This is a function template


template<class val> void swap(val &a, val &b)
{
val temp;
temp=a;
a=b;
b=temp;
}

int main(void)
{
int i=50, j=100;
double x=10.5, y=14.8;
char a='c', b='d';

cout<<"Original i, j: "<<i<<" "<<j<<"\n";

41
Object Oriented Programming through C++

cout<<"Original x, y: "<<x<<" "<<y<<"\n";


cout<<"Original a, b: "<<a<<" "<<b<<"\n\n";

swap(i, j); // swap integers


swap(x, y); // swap doubles
swap(a, b); // swap chars

cout<<"Swapped i, j: "<<i<<" "<<j<<"\n";


cout<<"Swapped x, y: "<<x<<" "<<y<<"\n";
cout<<"Swapped a, b: "<<a<<" "<<b<<"\n";
return 0;
}

Output:

Original i, j: 50 100
Original x, y: 10.5 14.8
Original a, b: c d

Swapped i, j: 100 50
Swapped x, y: 14.8 10.5
Swapped a, b: d c

Here, the line


template<class val> void swap(val &a, val &b);
tells the compiler two things: that a template is being created and that a generic definition is beginning. Here,
val is a generic type that is used as a placeholder. After the template portion, the function swap() is declared,
using val as the data type of the values that will be swapped. In main(), the swap() function is called using
three different types of data; ints, doubles, and chars. Because swap() is a generic function, the compiler
automatically creates three versions of swap(): one will exchange integer values, one will exchange double
values and the other one will exchange character values.

 Differences between Generic function and Overloaded function


Generic functions are similar to overloaded functions except that they are more restrictive.
When functions are overloaded, one may have different actions performed within the body of each
function. But a generic function must perform the same general action for all versions-only the type
of data can differ.

 A Function with two Generic Types

You can define more than one generic data type in the template statement by using a comma-
separated list. For example, this program creates a template function that has two generic types:

#include<iostream.h>
template <class type1, class type2> void func(type1 x, type2 y)
{
cout<<x<<" "<<y<<"\n";
}

42
Object Oriented Programming through C++

int main()
{
func(10, "I like C++");
func(14.56, 100L);
func('A', 67);
return 0;
}

In the above example, the placeholder types type1 and type2 are replaced by the compiler with the data types
int and char*, and double and long, and char and char*, respectively, when the complier generates the
specific instances of func() within main().

 Overloading a Generic Function

Even though a generic function overloads itself as needed, you can explicitly overload one, too. If
you overload a generic function, that overloaded function overrides the generic function relative to that
specific version. For example, consider the following program.

#include<iostream.h>
template<class X> void myfunc(X a)
{
cout<<"Inside template function "<<a<<"\n";

void myfunc(int a)
{
cout<<"Inside overloaded function "<<a<<"\n";
}
int main(void)
{
myfunc(10.84); myfunc(12L);
myfunc(50);
myfunc("C++ Programming");
return 0;
}

Output:

Inside template function 10.84


Inside template function 12
Inside overloaded function 50
Inside template function C++ Programming

As the comments inside the program indicates, when myfunc(10.84) is called, the compiler invokes the
template function but when myfunc(50) is called, the complier invokes the explicitly overloaded version of
myfunc() defined in the program. Thus, the compiler does not generate this version of the generic myfunc()
function, because the generic function is overridden by the explicit overloading.

43
Object Oriented Programming through C++

 Overloading a Function Template

We can overload a template function. To do so, simply create another version of the template that differs from
any others in its parameter list. For example,

//overload a template function declaration


#include<iostream.h>

template<class X> void func(X a)


{
cout<<"Value of a is "<<a<<"\n";
}

template<class X, class Y> void func(X a, Y b)


{
cout<<"Values of a and b are "<<a<<" "<<b<<"\n";
}

int main(void)
{
func(10);
func(10, 20);
return 0;
}

 Generic Classes

Like generic classes, we can create generic classes. The generic classes define the actual data type used by
that class. Those actual data types that will be manipulated by the class is specified as a parameter when
objects of that class are created. The compiler will automatically generate the correct type of object; based
upon the type you specify when the object is created.
The general from of a generic class declaration is shown here:

template <class type> class class_name


{
// body of the class
};

Here, type is the placeholder type name, which will be specified when a class is instantiated. If necessary, you
can define more than one generic data type using a comma-separated list.
Once you have created a generic class, you create a specific instance of that class using the following
general form:
class_name<type> ob;

Here, type is the type name of the data that the class will be operating upon. The following program is an
example of a generic class.

44
Object Oriented Programming through C++

/* This example uses two generic data types in a class definition*/


#include<iostream.h>
template<class Type1, class Type2> class myclass
{
Type1 x;
Type2 y;
public:
myclass(Type1 a, Type2 b)
{
x=a; y=b;
}
void show()
{
cout<<x<<" "<<y<<"\n";
}
};

int main(void)
{
myclass<int, double> ob1(10, 23.50);
myclass<char, char*> ob2('A', "Generic Class");
ob1.show(); ob2.show();
return 0;
}

------------------------------------------------------E N D-----------------------------------------------------------

45

You might also like