Lecture:10
Virtual Functions
Pointers To Derived Classes
A pointer declared as a pointer to a base class can also be used to point to any class derived from
that base. For example, assume two classes called base and derived, where derived inherits base.
base *p; // base class pointer
base base_ob ; // object of type base
derived derived_ob ; // object of type derived
p = & base_ob ; // p points to base object
p = & derived_ob ; // p points to derived object
One can use a base pointer to point to a derived object, one can access only those members of the
derived object that were inherited from the base. This is because the base pointer has knowledge
only of the base class. It knows nothing about the members added by the derived class.
Pointers To Derived Classes
While it is permissible for a base pointer to point to a derived object, the reverse is not true.
A pointer of the derived type cannot be used to access an object of the base class. (A type cast
can be used to overcome this restriction, but its use is not recommended practice.)
Pointer arithmetic is relative to the data type the pointer is declared as pointing to. Thus, if
you point a base pointer to a derived object and then increment that pointer, it will not be
pointing to the next derived object. It will be pointing to (what it thinks is) the next base
object.
Pointers To
Derived Classes
Pointers To Derived Classes
Explanation: A base pointer (p) can only interact with members inherited from the base class,
even when pointing to a derived object. To access derived-specific members, the derived object
must be used directly, as seen with d_ob accessing sety() and gety(). This behavior highlights how
base class pointers are restricted to base-level knowledge, ensuring compatibility in inheritance
hierarchies.
Pointers To Derived Classes
Task: On your own, try the preceding example and experiment with it.
For example, try declaring a derived pointer and having it access an
object of the base class.
Compile-time Polymorphism and Runtime
Polymorphism
Aspect Compile-Time Polymorphism Runtime Polymorphism
In compile-time polymorphism, the call is In runtime polymorphism, the call is not
Definition
resolved at compile time. resolved by the compiler.
It is also known as static binding, early binding, It is also known as dynamic binding, late
Binding
or overloading. binding, or overriding.
Achieved by using the same method name but
Method Achieved by overriding methods in the
with different arguments or parameters in the
Overloading/Overriding derived classes to suit their requirements.
same or different scope.
Achieved by function overloading and operator
Techniques Achieved by virtual functions and pointers.
overloading.
Provides slow execution as compared to
Provides fast execution because the method to be
Execution Speed compile-time polymorphism because the
executed is known early at compile time.
method to be executed is known at runtime.
Function Overloading vs
Function Overriding
Virtual Function
A virtual function (also known as virtual methods) is a member function that is declared within
a base class and is re-defined (overridden) by a derived class. When you refer to a derived class
object using a pointer or a reference to the base class, you can call a virtual function for that
object and execute the derived class’s version of the method.
• Virtual functions ensure that the correct function is called for an object, regardless
of the type of reference (or pointer) used for the function call.
• They are mainly used to achieve Runtime polymorphism.
• Functions are declared with a virtual keyword in a base class.
• The resolving of a function call is done at runtime.
Rules for Virtual Functions
The rules for the virtual functions in C++ are as follows:
• Virtual functions cannot be static.
• A virtual function can be a friend function of another class.
• Virtual functions should be accessed using a pointer or reference of base class type to
achieve runtime polymorphism.
• The prototype of virtual functions should be the same in the base as well as the derived
class.
• They are always defined in the base class and overridden in a derived class. It is not
mandatory for the derived class to override (or re-define the virtual function), in that case,
the base class version of the function is used.
• A class may have a virtual destructor but it cannot have a virtual constructor.
Static Member Functions
•These functions belong to the class itself, not to any specific object.
•They can only access static members of the class, which are shared among all objects of that
class.
•No this pointer is passed because static functions don’t operate on individual object data.
•You can call static functions without creating an object.
class Car {
static int totalCars; // static member (shared by all Car objects)
public:
static void setTotalCars(int count) { // static function
totalCars = count; }
static int getTotalCars() {return totalCars; }};
int main()
{ Car::setTotalCars(5);
cout << "Total Cars: " << Car::getTotalCars() << endl;
Return 0;}
Non- Static Member Functions
•These functions belong to individual objects of a class.
•Every time you create an object, that object has its own separate copy of the non-static data
members, and non-static functions work on that data.
•Non-static functions can access both static and non-static members (variables or functions) of
the class.
•The this pointer is passed to non-static functions, which points to the current object calling the
function. This allows the function to know which object's data to use.
class Car {
int speed; // non-static member
public:
void setSpeed(int s) { // non-static function
speed = s; // works on the speed of the object calling it
}};
Virtual Functions
Virtual Function
[Link] Function (display): The function display in GFG_Base is declared as virtual. This
allows GFG_Child to override display with its own version. When you call base->display(), the actual object
type (in this case, GFG_Child) determines which version of the function to execute. So, base->display() calls
the GFG_Child's version of display.
[Link]-Virtual Function (print): The function print in GFG_Base is not virtual. This means the function is
resolved at compile time, based on the type of the pointer (GFG_Base*). So, base->print() calls the GFG_Base's
version of print, even though the pointer points to a GFG_Child object.
Virtual Functions
Virtual Function
[Link] Function: The function print in base is declared as virtual. This allows derived to override print with its
own version. When you call bptr->print(), the actual object type (in this case, derived) determines which version of
the function to execute. So, bptr->print() calls the derive’s version of print.
[Link]-Virtual Function (display): The function display in base is not virtual. This means the function is resolved
at compile time, based on the type of the pointer (base*). So, bptr->display(), calls the base's version of display,
even though the pointer points to a derive object.
Virtual Functions
Virtual Function
Explanation: As you can see, the example program creates three classes. The base class defines the
virtual function func(). This class is then inherited by both derived1 and derived2. Each of these classes
overrides func() with its individual implementation. Inside main(), the base class pointer p is declared along
with objects of type base, derived1, and derived2. First, p is assigned the address ob ob (an object of type
base). When func() is called by using it, it is the version in base that is used. Next, p is assigned the address of
d_ob1 and func() is called again. Because it is the type of the object pointed to that determines which virtual
function will be called, this time it is the overridden version in derived1 that is executed. Finally, p is assigned
the address of d_ob2 and func() is called again, This time, it is the version of func() defined inside derived2
that is executed.
Virtual Functions
Virtual functions are hierarchical in
order of inheritance. Further, when a
derived class does not override a
virtual function, the function defined
within its base class is used. For
example, here is a slightly different
version of the preceding program:
Virtual Functions
Virtual Function
Explanation: In this version, derived2 does not override func(). When p is assigned d ob2
and func() is called, base's version is used because it is next up in the class hierarchy. In
general, when a derived class does not override a virtual function, the base class's version
is used.
Virtual Functions
It is allowed to call the virtual
function of the grandparent class
from the child class in case of
multilevel inheritance. Virtual
functions ensure that the most
overridden version of the
function is invoked, depending on
the actual type of the object being
used.
Virtual Function
If you use a GrandParent* or Parent* pointer to refer to the Child object, the virtual
function mechanism ensures that the Child's overridden version of display() is called.
Even though the function is overridden at each level, you can still directly access the base
class versions when needed.
Advantages of using Virtual Function
• The derived class's overridden method is executed, even when a base class pointer/reference is used.
base->display(); // Calls Derived class method, if base points to a derived object.
This behavior is resolved at runtime (called runtime binding or dynamic dispatch).
• In large applications, you might have multiple derived classes from a common base class. With virtual functions, you
can create generic code that can handle different derived classes dynamically. For example, if you have multiple shapes
like Circle, Rectangle, and Triangle derived from Shape, you can write:
Shape* shape = getShape(); // Dynamically return any type of shape
shape->draw(); // Correct `draw` method is called (Circle, Rectangle, or Triangle)
Without virtual functions, you would need to manually check the type of the object and call the appropriate method.
• Virtual functions allow you to use the same interface for multiple derived classes. You don’t need to rewrite or
duplicate code for each derived class. You can write code once in terms of the base class and let the derived classes
implement specific behaviors.
Pure Virtual Function & Abstract Class
• A pure virtual function (or abstract function) in C++ is a virtual function for which there
is no implementation/ definition in the base class, and we must override that function in the
derived class, otherwise, the derived class will also become an abstract class.
• A pure virtual function is declared by assigning 0 in the declaration.
• Sometimes implementation of all functions cannot be provided in a base class because we
don’t know the implementation. Such a class is called an abstract class.
• When a class contains at least one pure virtual function, it is referred to as an abstract class.
Pure Virtual Function & Abstract Class
● For example, let Shape be a base class. We cannot provide the implementation of function
draw() in Shape, but we know every derived class must have an implementation of draw().
Similarly, an Animal class doesn’t have the implementation of sound() (assuming that all
animals sound), but all animals must know how to make sound.
● Since an abstract class contains at least one function for which no body exists, it is,
technically, an incomplete type, and no objects of that class can be created.
● Thus, abstract classes exist only to be inherited.
● You can still create a pointer to an abstract class.
Pure
Virtual
Functions
Pure
Virtual
Functions
Facts on Pure Virtual Functions & Abstract Class
1. A class is abstract if it has at least one pure virtual function.
Facts on Pure Virtual Functions & Abstract Class
2. We can have pointers and references of abstract class type.
Facts on Pure Virtual Functions & Abstract Class
3. If we do not override the pure virtual function in the derived class, then the derived class
also becomes an abstract class.
Facts on Pure Virtual
Functions & Abstract
Class
4. An abstract class can have
constructors.
Facts on Pure Virtual Functions & Abstract Class
5. An abstract class in C++ can also be defined using struct keyword.
Example
struct shapeClass
{
virtual void Draw()=0;
}
Virtual Functions vs Pure Virtual Functions
Virtual function Pure virtual function
A pure virtual function is a member function of base class
A virtual function is a member function of base class whose only declaration is provided in base class and
which can be redefined by derived class. should be defined in derived class otherwise derived class
also becomes abstract.
Base class containing pure virtual function becomes
Classes having virtual functions are not abstract.
abstract.
Definition is given in base class.
No definition is given in base class.
Base class having pure virtual function becomes abstract
Base class having virtual function can be instantiated i.e.
i.e. it cannot be instantiated.
its object can be made.
If derived class does not redefine virtual function of the
If derived class does not redefine virtual function of the
base class, then no compilation error is encountered, but
base class, then it does not affect compilation.
like the base class, derived class also becomes abstract.
Practice Task
1. Design a base class Base with a member length and a pure virtual function area().
Derived class Square overrides the area() function to calculate area of a square.
Another Derived class Cube overrides the area() function to calculate area of a cube.
Create a square and a cube object and find their area in main function.
2. Design an abstract class named Vehicle with an abstract method fuelType(). Create
derived classes Car and Bike. The Car class should define fuelType() to output
"Petrol" and the Bike class should define fuelType() to output "Diesel". Demonstrate
the usage in a main function.
3. Create a simple ‘shape’ hierarchy: a base class called Shape and derived classes
called Circle, Square, and Triangle. In the base class, make a virtual function
called draw( ), and override this in the derived classes.
Thank You