A virtual function in C++ is a member function in a base class that you expect to be overridden in derived classes. When a function is declared as virtual, C++ uses a mechanism known as dynamic dispatch or runtime polymorphism to determine which function to call, based on the actual type of the object pointed to, rather than the type of the pointer or reference. This is a key concept in object-oriented programming, allowing for more flexible and reusable code.
virtual
Keyword: The virtual keyword is used in the base class to indicate that a function is intended to be overridden in derived classes.virtual
table) to manage virtual
functions. Each class with virtual
functions has a vtable that holds pointers to the virtual
functions, and each object of that class has a pointer to the vtable
(called a vpointer
).Here's a simple example demonstrating how virtual functions work in C++:
#include <iostream>
class Base {
public:
virtual void show() {
std::cout << "Base class show() function called." << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // Override the base class function
std::cout << "Derived class show() function called." << std::endl;
}
};
int main() {
Base* basePtr;
Derived derivedObj;
basePtr = &derivedObj;
// This will call the derived class's show() method
basePtr->show();
return 0;
}
virtual
Keyword: The show()
function in the Base
class is declared as virtual
. This means it can be overridden in derived classes.show()
function is overridden in the Derived
class. The override
keyword is used for clarity (optional, but recommended in modern C++).basePtr
is of type Base*
, but it points to a Derived
object. When basePtr->show()
is called, the Derived
class's show()
function is invoked, demonstrating runtime polymorphism.A pure virtual function is a virtual function that has no implementation in the base class and must be overridden in any derived class. A class containing at least one pure virtual function is known as an abstract class and cannot be instantiated.
#include <iostream>
class Shape {
public:
virtual void draw() = 0; // Pure virtual function
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing Circle." << std::endl;
}
};
class Square : public Shape {
public:
void draw() override {
std::cout << "Drawing Square." << std::endl;
}
};
int main() {
Shape* shape;
Circle circle;
Square square;
shape = &circle;
shape->draw(); // Calls Circle's draw()
shape = □
shape->draw(); // Calls Square's draw()
return 0;
}
draw()
function in the Shape
class is declared as virtual void draw() = 0;
. This makes Shape
an abstract class
.Shape
cannot be instantiated directly; you can only create objects of derived classes that override all pure virtual functions.Circle
and Square
override the draw()
function.shape
pointer is used to call the draw()
function, demonstrating polymorphism as it calls the correct draw()
method depending on the type of object it points to.When dealing with inheritance, especially with virtual functions, it's crucial to define a virtual destructor
in the base class. This ensures that the destructor for derived classes is called correctly when an object is deleted through a base class pointer.
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor called." << std::endl;
}
virtual ~Base() { // Virtual destructor
std::cout << "Base destructor called." << std::endl;
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor called." << std::endl;
}
~Derived() {
std::cout << "Derived destructor called." << std::endl;
}
};
int main() {
Base* basePtr = new Derived();
delete basePtr; // Correctly calls Derived's destructor followed by Base's destructor
return 0;
}
Base
class is declared as virtual ~Base()
. This ensures that the destructor of the derived class is called when deleting an object through a base class pointer.basePtr
is called, it first invokes Derived
's destructor and then Base
's destructor, ensuring proper resource cleanup.When dealing with multiple inheritance, C++ resolves virtual functions correctly by looking at the most derived class.
#include <iostream>
class A {
public:
virtual void show() {
std::cout << "A's show() called." << std::endl;
}
};
class B : public A {
public:
void show() override {
std::cout << "B's show() called." << std::endl;
}
};
class C : public B {
public:
void show() override {
std::cout << "C's show() called." << std::endl;
}
};
int main() {
A* ptr = new C();
ptr->show(); // Calls C's show()
delete ptr;
return 0;
}
C
inherits from B
, which inherits from A
.C
overrides the show()
function, and even though ptr is of type A*
, it calls C
's show()
function because ptr actually points to an object of type C
.vtable
) to resolve which function to call at runtime based on the actual object type.Understanding virtual functions is fundamental to mastering object-oriented programming in C++. They enable polymorphism, one of the key principles of OOP, allowing you to write more flexible and reusable code.
Previous Page | Course Schedule | Course Content