KEMBAR78
BCS306B - Module 4 | PDF | Inheritance (Object Oriented Programming) | Class (Computer Programming)
0% found this document useful (0 votes)
5 views11 pages

BCS306B - Module 4

Djsnakasksmsjsk

Uploaded by

Fake World
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views11 pages

BCS306B - Module 4

Djsnakasksmsjsk

Uploaded by

Fake World
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

BCS306B Virtual Functions and Polymorphism, Templates Module 4

Module 4
VIRTUAL FUNCTIONS AND POLYMORPHISM
Introduction
Polymorphism is one of the crucial features of OOP. It simply means ‘having many
forms’. Polymorphism can be achieved in two levels, one at compile time and another at run-
time. In C++, compile time polymorphism is achieved using overloaded functions and
operators, and the run time polymorphism is achieved using the virtual functions. The
implementation of virtual functions requires the use of pointers to objects.
Polymorphism

Compile-time Run-time

Function Operator Virtual


Overloading Overloading functions
Virtual Functions:
When we use the same function name in both the based and derived classes, the
function in base class is declared as virtual using the keyword virtual preceding its normal
declaration. When a function is made virtual, C++ determines which function to use at run
time based on the type of object pointed to by the base pointer, rather than the type of the
pointer. Thus, by making the base pointer to point to different objects, we can execute
different versions of the virtual functions.

Rules for Virtual Functions:


When virtual functions are created for implementing late binding, we should observe
some basic rules that satisfy the compiler requirements:
1. The virtual functions must be member of some class.
2. They cannot be static member function.
3. They are accessed by using object pointers.
4. A virtual functions can be a friend of another class.
5. They should be declared in public section of the class.
6. The prototypes of the base class version of a virtual function and all the derived class
versions must be identical. (If two functions with the same name have different
prototypes, C++ considers them as overloaded functions.)
7. We cannot have virtual constructors, but we can have virtual destructors.
8. While a base pointer can point to any type of the derived object, the reverse is not true.
9. If a virtual function is defined in the base class, it need not be necessarily redefined in the
derived class. In such cases, calls will invoke the base function.

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 1


BCS306B Virtual Functions and Polymorphism, Templates Module 4

Example Program 1:
class baseclas
{
public:
virtual void virtfunc( )
{
cout<<”This is baseclas’s virtfunc ( )”<<endl;
}
};
class derivedclas1 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas1’s virtfunc ( )”<<endl;
}
};
class derivedclas2 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas2’s virtfunc ( )”<<endl;
}
};
void main( )
{ OUTPUT:
baseclas *ptr, b; This is baseclas’s virtfunc ( )
derivedclas d1; This is derivedclas1’s virtfunc ( )
derivedclas d2;
This is derivedclas2’s virtfunc ( )
ptr = &b; // Point to baseclas
ptr -> virtfunc( ); // Access baseclas’s virtfunc( )
ptr = &d1; // Point to derivedclas1
ptr -> virtfunc( ); // Access derivedclas1’s virtfunc( )
ptr = &d2; // Point to derivedclas2
ptr -> virtfunc( ); // Access derivedclas2 virtfunc( )
getch();
}
Here, the address of the object b is stored in ptr (is a pointer variable). Then we are
accessing the member function virtfunc( ) through the ptr. Next the address of the object d1 is
stored in ptr and accessing the member function virtfunc( ) through the ptr.
Finally the address of the object d2 is stored in ptr and accessing the member function
virtfunc( ) through the ptr. It is also possible to access virtfunc( ) through the objects
directly. (i.e., b.virtfunc( ) )

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 2


BCS306B Virtual Functions and Polymorphism, Templates Module 4

Calling a Virtual Function through a Base Class Reference:


In the previous example program, virtual functions were invoked by base class pointer.
In this section, the polymorphic nature of virtual functions are also available when we called by
a base class reference.
A reference is an implicit pointer. Thus a base class reference can be used to refer to an
object of the base class or any object of derived class from that base classWhen a virtual
function is called by a base class reference, the version of the function is determined by the
object being referred to at the time of call and the function parameter as reference.
Example Program 2:
class baseclas
{
public: virtual void virtfunc( )
{
cout<<”This is baseclas’s virtfunc ( )”<<endl;
}
};
class derivedclas1 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas1’s virtfunc ( )”<<endl;
}
};
class derivedclas2 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas2’s virtfunc ( )”<<endl;
}
};
void func(base &ref)
{
ref.virtfunc( );
}
void main( ) OUTPUT:
{ This is baseclas’s virtfunc ( )
baseclas b; This is derivedclas1’s virtfunc ( )
derivedclas d1; This is derivedclas2’s virtfunc ( )
derivedclas d2;
func(b); // Passes the baseclas’s object to func( )
func(b); // Passes the derivedclas1’s object to func( )
func(b); // Passes the derivedclas2’s object to func( )
}
Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 3
BCS306B Virtual Functions and Polymorphism, Templates Module 4

This program gives the same out as in the previous example program. In this program,
the function func( ) defines a reference parameter of type base. Inside the main( ), the function
is called using objects of type baseclas, derivedclas1, derivedclas2.

The Virtual Attribute is Inherited:


In C++, when a virtual function is inherited, then its virtual nature is also inherited. This
means one derived class inherited to another derived class as base class, then the virtual
function can still be overridden. No matter put differently, how many times a virtual function is
inherited, it remains virtual. In the following program, derivedclas2 inherits derivedclas1
instead of baseclas, but virtfunc( ) is still virtual.
Example Program 3:
class baseclas
{
public:
virtual void virtfunc( )
{
cout<<”This is baseclas’s virtfunc ( )”<<endl;
}
};
class derivedclas1 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas1’s virtfunc ( )”<<endl;
}
};
OUTPUT:
class derivedclas2 : public derivedclas1
This is baseclas’s virtfunc ( )
{
This is derivedclas1’s virtfunc ( )
public:
void virtfunc( ) This is derivedclas2’s virtfunc ( )

{
cout << ”This is derivedclas2’s virtfunc ( ) \n ;
}
};
void main( )
{
baseclas *ptr, b;
derivedclas d1;
derivedclas d2;

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 4


BCS306B Virtual Functions and Polymorphism, Templates Module 4

ptr = &b; // Point to baseclas


ptr -> virtfunc( ); // Access baseclas’s virtfunc( )
ptr = &d1; // Point to derivedclas1
ptr -> virtfunc( ); // Access derivedclas1’s virtfunc( )
ptr = &d2; // Point to derivedclas2
ptr -> virtfunc( ); // Access derivedclas2’s virtfunc( )
getch( );
}

Virtual Functions are Hierarchical:


As we know, when a function is declared as virtual by a base class, it may overridden
by derived class. However, that function no need to be overridden. Suppose a derived class fails
to override a virtual function, then when the object of that derived class invokes that function,
then the function defined by the base class is used. In the following program, derivedclas2
doesnot override virtfunc( ) but invokes virtfunc( ) of baseclas.
Example Program 4:
class baseclas
{
public:
virtual void virtfunc( )
{
cout<<”This is baseclas’s virtfunc ( ) \n” ;
}
};
class derivedclas1 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas1’s virtfunc ( )”<<endl;
}
};
class derivedclas2 : public baseclas
{
public: // Here, virtfunc( ) is not overridden by derivedclas2, but baseclas’s is used
};
void main( )
{
baseclas *ptr, b;
OUTPUT:
derivedclas d1;
This is baseclas’s virtfunc ( )
derivedclas d2;
This is derivedclas1’s virtfunc ( )
ptr = &b; // Point to baseclas
This is baseclas’s virtfunc ( )
ptr -> virtfunc( ); // Access baseclas’s virtfunc( )

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 5


BCS306B Virtual Functions and Polymorphism, Templates Module 4

ptr = &d1; // Point to derivedclas1


ptr -> virtfunc( ); // Access derivedclas1’s virtfunc( )
ptr = &d2; // Point to derivedclas2
ptr -> virtfunc( ); // use baseclas’s virtfunc( )
}
In C++, as inheritance is hierarchical, it makes sense that virtual function are also
hierarchical. This means that when a derived class fails to override a virtual function, the
redefinition found in reverse order of derivation is used. In the following program,
derivedclas2 is derived from derivedclas1, which is derived from baseclas. doesnot override
virtfunc( ) but invokes virtfunc( ) of baseclas. So here derivedclas2 doesn’t override virtfunc(
) of baseclas but it overrides virtfunc( ) of derivedclas1 as it is closest version to
derivedclas2.
Example Program 5:
class baseclas
{
public: virtual void virtfunc( )
{
cout<<”This is baseclas’s virtfunc ( )”<<endl;
}
};
class derivedclas1 : public baseclas
{
public:
void virtfunc( )
{
cout<<”This is derivedclas1’s virtfunc ( )”<<endl;
}
};
class derivedclas2 : public derivedclas1
{
public: // Here, virtfunc( ) is not overridden by derivedclas2, but derivedclas1’s is used
}; OUTPUT:
void main( )
{ This is baseclas’s virtfunc ( )
baseclas *ptr, b; This is derivedclas1’s virtfunc ( )
derivedclas d1; This is derivedclas1’s virtfunc ( )
derivedclas d2;
ptr = &b; // Point to baseclas
ptr -> virtfunc( ); // Access baseclas’s virtfunc( )
ptr = &d1; // Point to derivedclas1
ptr -> virtfunc( ); // Access derivedclas1’s virtfunc( )
ptr = &d2; // Point to derivedclas2
ptr -> virtfunc( ); // use derivedclas1’s virtfunc( )
}

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 6


BCS306B Virtual Functions and Polymorphism, Templates Module 4

Pure Virtual Functions:


It is normal practice to declare a function virtual inside the base class and redefined it
in the derived classes. The base class version of the function is not always utilized to perform
the specific task. It serves merely as placeholder to be overridden by the derived class
versions.

A pure virtual function is a function declared in a base class that has no definition
relative to the base class.
Properties of pure Virtual functions:
• A pure virtual function is “do-nothing” member function.
• It has no definition in the base class but has declaration.
• A class having pure virtual functions cannot be used to instantiate objects of its own.
Example:
virtual void display( ) = 0;
where,
virtual : is the keyword
void : the return type of the function
display : is a pure virtual function
Also note here that the function is initialised 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 occur.
Example Program 5:
class baseclas
{
protected:
int value;
public:
void setvalue(int x)
{
value = x;
}
virtual void display( ) = 0;
};
class deci : public baseclas
{
public:
void display( )
{
cout<< value << endl;
}
};

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 7


BCS306B Virtual Functions and Polymorphism, Templates Module 4

class hexa : public baseclas


{
public:
void display( )
{
cout<< hex << “\t”<< value << endl;
}
};
class octa : public baseclas
{
public: void display( )
{
cout<< octa << “\t” << value << endl;
}
};
void main( )
{
deci d;
hexa h;
octa o;
d.setvalue(20);
d.display( ); // Display 20 – Decimal OUTPUT:
h.setvalue(20); 20
h.display( ); // Displays 14 – Hexadecimal 14 20
o.setvalue(20);
24 20
o.display( ); // Displays 24 – Octal
}
Abstract Classes:
A class that contains atleast one pure virtual function is called as Abstract class.
An abstract class contains one or more pure virtual functions for which there is no
definition, no objects may be created. Instead, an abstract class constitutes incomplete but it
is a foundation for derived classes.

We cannot create objects but can create pointers and references to an abstract class.
This allows abstract classes to support run time polymorphism.
An important use of abstract classes and virtual functions is in class libraries. Using
these, we can create a generic, extensible class library that will be used by other programmer.
Using Virtual Functions:
In OOP, one of the central aspects is the principle of “One Interface, Multiple
Methods”. This means that in a general base class we have to define all the common features
of actions which can be used by all the derived classes. This interface (i.e., class) is constant.
Then each derivation defining its own specific operations along with the usage of base class’s
common features of actions.

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 8


BCS306B Virtual Functions and Polymorphism, Templates Module 4

One of the most powerful, most useful, and flexible ways to implement the “One
Interface, Multiple Methods” approach is to use Virtual Functions, Abstract Classes, and
Runtime Polymorphism.
Using these features, we can create a class hierarchy that moves from generic to
specific (base class to derived class). Using this philosophy, we define all the common
features and interfaces in base class and define certain different actions can be implemented
in different derived classes.
The following C++ program to illustrate the above philosophy
class convert // class contains all common features
{
protected: double value1, value2; //for initial and converted value respectively
public:
convert(double i)
{
value1 = i;
}
double getconvalue( )
{
return value2;
}
double getinitvalue( )
{
return value1;
}
virtual void compute ( ) = 0;
};
class f_to_c : public convert // class which converts Fahrenheit to Celsius
{
public:
f_to_c(double i) : convert (i)
{
}
void compute( )
{
value2 = (value1-32)/1.8;
}
};
class f_to_m : public convert // class which converts Feet to Meters
{
public:

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 9


BCS306B Virtual Functions and Polymorphism, Templates Module 4

f_to_m(double i) : convert (i)


{
}
void compute( )
{
value2 = value1/3.28;
}
};
void main( )
{
convert *ptr; // Ponter to base class
f_to_c fc(70);
f_to_m fm(100);
ptr = &fc;
cout<< ptr-> getinitvalue( ) << “Fehrenheit is \n”;
ptr->compute( );
cout<< ptr-> getconvalue( ) << “Celcius\n”;
ptr = &fm;
cout<< ptr-> getinitvalue( ) << “Feet is \n”;
ptr->compute( );
cout<< ptr-> getconvalue( ) << “Meter\n”;
}
One of the benefits of derived classes and virtual functions is that handling a new class
is very easy. For example
class l_to_g : public convert // class which converts Liters to Gallons
{
public:
l_to_g(double i) : convert (i)
{
}
void compute( )
{
value2 = value1/3.7854;
}
};
NOTE: The base class convert is an example of Abstract Class. The virtual function
compute( ) is not defined within convert because no meaningful definition is can be provided.
It is only when convert is inherited by a derived class that complete type is created.

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 10


BCS306B Virtual Functions and Polymorphism, Templates Module 4

Early and Late Binding:


Early Binding:

Events that occur at compile time are referred as Early Binding. It means an object and a
function call are bound during compilation.
For example: Normal function calls (including library function calls), overloaded
function calls, and overloaded operators.
Advantage of early binding is Efficiency. Because all information necessary to call a
function is determined at compile time. So these types of function calls executes very fast.
Late Binding:
Function calls that are not resolved until run time are referred as Late Binding.

For example: Virtual functions, access via a base pointer or reference, the virtual
functions actually called are determined by the type of object pointed to by the pointer.
Advantage of late binding is Flexibility. Late binding allows us to create programs
that can respond to events occurring while the program executes without having to create a
large amount of “Contingency Code”.
Late binding can make for somewhat slower execution times as function call is not
resolved until run time.

Dr.Shivashankara S, Dept. of CS & E, KR Pete Krishna Govt. Engg. College, Krishnarajapet 11

You might also like