Free tutorials & notes in Hindi & English · Clean code examples · Mobile friendly learning
🟣 OOP  ·  Lesson 48

Virtual Functions

Written and reviewed by · Senior IT Faculty · 15+ years’ experience

What is a virtual function?

A virtual function is a member function marked virtual in a base class, designed to be overridden by derived classes. Its point is dynamic dispatch: when you call it through a base-class pointer or reference, C++ runs the version belonging to the actual object, not the pointer's type.

The problem it solves

Without virtual, a call through a base pointer always runs the base version, ignoring the override. Compare:

C++
class Base { public: virtual void hi() { cout << "Base\n"; } };
class Derived : public Base { public: void hi() override { cout << "Derived\n"; } };

int main() {
    Base *p = new Derived();
    p->hi();          // "Derived" — thanks to virtual
    delete p;
}
Output:
Derived

Remove virtual and this would print Base instead.

The override keyword

Add override to a derived function you intend as an override. If it does not actually match a base virtual, the compiler stops you — catching typos in the signature:

C++
class Shape { public: virtual double area() { return 0; } };
class Circle : public Shape {
    double r;
public:
    Circle(double x) : r(x) {}
    double area() override { return 3.14159 * r * r; }  // safe
};

How it works: the vtable

Most compilers implement this with a vtable — a per-class table of function pointers. Each polymorphic object holds a hidden pointer to its class's vtable, and a virtual call looks up the right function there at run time. This is why virtual calls have a tiny overhead over ordinary calls.

Virtual destructors

If you delete a derived object through a base pointer, the destructor must be virtual — otherwise only the base part is destroyed and the derived resources leak:

C++
class Base {
public:
    virtual ~Base() { cout << "~Base\n"; }   // virtual destructor
};
class Derived : public Base {
public:
    ~Derived() { cout << "~Derived\n"; }
};
// delete (Base*)new Derived();  → ~Derived then ~Base
💡 Rule

Any class with a virtual function should also have a virtual destructor.

Overriding vs hiding

True overriding needs a matching signature on a virtual base function. If the base function is not virtual, or the signatures differ, the derived function merely hides the base one — no dynamic dispatch. The override keyword guards against this by mistake.

Common mistakes

  • Forgetting virtual, so overrides are ignored through base pointers.
  • Omitting a virtual destructor in a polymorphic base (resource leak).
  • A slightly different signature causing hiding instead of overriding (use override).
  • Expecting dynamic dispatch when calling on an object rather than a pointer/reference.

For a compact syntax reference and quick example, see the virtual functions syntax page. For the wider idea, see polymorphism.

🏋️ Practice

Build a Shape base with a virtual area() and a virtual destructor. Derive Circle and Rectangle. Store them via Shape* pointers and print each area through the base pointer.

Summary

  • A virtual function enables run-time dispatch to the right override.
  • Call it through a base pointer/reference for polymorphism.
  • override makes the compiler verify your override.
  • Compilers use a vtable to resolve virtual calls at run time.
  • Always give a polymorphic base class a virtual destructor.

Frequently Asked Questions

What is a virtual function in C++?
A virtual function is a member function declared with the virtual keyword in a base class, meant to be overridden in derived classes. When called through a base-class pointer or reference, the version matching the actual object is chosen at run time, enabling run-time polymorphism.
What does the override keyword do in C++?
The override keyword tells the compiler that a function is meant to override a virtual function from the base class. If the signature does not actually match a base virtual function, the compiler reports an error, which catches subtle mistakes early.
How do virtual functions work internally in C++?
Most compilers implement virtual functions using a vtable — a table of function pointers per class. Each object of a polymorphic class holds a hidden pointer to its class's vtable, and a virtual call looks up the correct function through that table at run time.
Why do you need a virtual destructor in C++?
When you delete a derived object through a base-class pointer, the destructor must be virtual so the derived destructor runs too. Without a virtual destructor only the base part is destroyed, leaking the derived class's resources, so polymorphic base classes should always have one.
What is the difference between overriding and function hiding in C++?
Overriding replaces a base virtual function with a matching derived one, chosen at run time. Function hiding happens when a derived class declares a function with the same name but the base version is not virtual or the signature differs, so the base version is simply hidden rather than polymorphically overridden.

Virtual function क्या है?

Virtual function एक member function है जो base class में virtual चिह्नित होता है, derived classes द्वारा override होने को बना। इसका उद्देश्य dynamic dispatch है: जब आप इसे base-class pointer या reference के ज़रिए call करते हैं, C++ वास्तविक object का version चलाता है, pointer के type का नहीं।

यह किस समस्या को हल करता है

virtual के बिना, base pointer के ज़रिए call हमेशा base version चलाता है, override को अनदेखा करते हुए। तुलना करें:

C++
class Base { public: virtual void hi() { cout << "Base\n"; } };
class Derived : public Base { public: void hi() override { cout << "Derived\n"; } };

int main() {
    Base *p = new Derived();
    p->hi();          // "Derived" — virtual ki wajah se
    delete p;
}
Output:
Derived

virtual हटाएँ और यह इसके बजाय Base print करेगा।

override keyword

जिस derived function को आप override बनाना चाहते हैं उसमें override जोड़ें। अगर यह वास्तव में किसी base virtual से मेल न खाए, compiler आपको रोकता है — signature में typos पकड़ते हुए:

C++
class Shape { public: virtual double area() { return 0; } };
class Circle : public Shape {
    double r;
public:
    Circle(double x) : r(x) {}
    double area() override { return 3.14159 * r * r; }  // safe
};

यह कैसे काम करता है: vtable

अधिकांश compilers इसे vtable से लागू करते हैं — प्रति-class function pointers की तालिका। हर polymorphic object अपनी class के vtable का एक छिपा pointer रखता है, और virtual call run time पर वहाँ सही function ढूँढता है। इसीलिए virtual calls में सामान्य calls पर एक छोटा overhead होता है।

Virtual destructors

अगर आप base pointer के ज़रिए derived object delete करते हैं, destructor virtual होना चाहिए — अन्यथा केवल base हिस्सा नष्ट होता है और derived resources leak होते हैं:

C++
class Base {
public:
    virtual ~Base() { cout << "~Base\n"; }   // virtual destructor
};
class Derived : public Base {
public:
    ~Derived() { cout << "~Derived\n"; }
};
// delete (Base*)new Derived();  → pehle ~Derived phir ~Base
💡 नियम

किसी भी class में virtual function हो तो उसमें virtual destructor भी होना चाहिए।

Overriding बनाम hiding

सच्चे overriding को virtual base function पर मेल खाता signature चाहिए। अगर base function virtual न हो, या signatures भिन्न हों, derived function केवल base को छिपाता है — कोई dynamic dispatch नहीं। override keyword इसे गलती से होने से रोकता है।

आम गलतियाँ

  • virtual भूलना, तो base pointers के ज़रिए overrides अनदेखे होते हैं।
  • Polymorphic base में virtual destructor छोड़ना (resource leak)।
  • थोड़ा अलग signature overriding के बजाय hiding पैदा करना (override इस्तेमाल करें)।
  • Pointer/reference के बजाय object पर call करते समय dynamic dispatch की उम्मीद।

संक्षिप्त syntax reference और त्वरित उदाहरण के लिए, virtual functions syntax page देखें। व्यापक विचार के लिए, polymorphism देखें।

🏋️ अभ्यास

एक Shape base बनाएँ जिसमें virtual area() और virtual destructor हो। Circle और Rectangle derive करें। इन्हें Shape* pointers से रखें और हर area base pointer के ज़रिए print करें।

सारांश

  • Virtual function सही override को run-time dispatch सक्षम करता है।
  • Polymorphism के लिए इसे base pointer/reference के ज़रिए call करें।
  • override compiler से आपका override सत्यापित कराता है।
  • Compilers virtual calls run time पर हल करने को vtable इस्तेमाल करते हैं।
  • Polymorphic base class को हमेशा virtual destructor दें।
← Back to C++ Tutorial
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.