Virtual Destructors : Unwinding the Existence

This blog aims to enrich your understanding of how virtual destructors. By exploring their necessity in polymorphic class hierarchies, we’ll shed light on common pitfalls and how to avoid them, ensuring your applications are not only functional but also well-architected. Whether you’re a beginner or an experienced developer, this short guide will provide valuable insights into making your code more robust and maintainable.

Destructors and Virtual Destructors

  • Call Hierarchy:
    • In C++ polymorphism, constructors and destructors uniquely auto-chain calls within the inheritance hierarchy. They are the only places where compiler automatically orchestrates hierarchy of calls. No such hierarchy exists for ordinary member functions (virtual or not).
  • Virtual functions:
    • Virtual functions operate in the same way for all member functions, “including destructors”. Constructors are the only exception where the concept of virtuality does not apply.
  • Never forget the Virtual destructor:
    • Forgetting to make destructors virtual within polymorphic hierarchy can introduce critical bugs which may not manifest in your program behaviour. Since destruction processes are often silent, the absence of a virtual destructor can quietly erode program integrity.

Virtual in constructors & destructors

  • There is no such thing as “virtual constructor”:
    • You can’t use virtual keyword with constructors.  Constructors are responsible for initializing an object’s state before it is used, having a “virtual constructor” would imply a need for runtime decision-making before the type of the object is fully created, which contradicts the compile-time nature of object creation in C++. Thus, the design and purpose of constructors inherently preclude them from being virtual.
  • Virtual mechanism is “ignored” from constructor and destructors:
    • Call to virtual functions from constructors and destructors always resolve to local versions of the virtual functions.
      • In the case of constructor – to prevent possible virtual function call resolution to a function that is “further-down” (more derived) in the inheritance hierarchy than the current constructor. So that actual function call would rely on partitions of the object that are “not yet created”.
      • In the case of destructors – Information about the possible virtual function call resolution is “available, but it isn’t reliable”. In that, the actual function call would rely on portions of the object which have “already been destroyed”.

Pure virtual destructors

  • Pure virtual destructors are unique:
    • They are unique in that unlike other virtual functions you must provide the function body for pure virtual destructors.
      • During object destruction, all the destructors in the inheritance hierarchy should always be called. Without the function body for the pure virtual destructor, there can’t be a call to the base version of the destructor.
      • This case doesn’t arise in ordinary virtual functions as there is no such thing as hierarchy there (as discussed above only constructors and destructors have hierarchical calls orchestrated by the compiler).
  • Compiler dependancy:
    • A base class and all its derived classes become abstract if they contain pure virtual destructors and do not implement all other pure virtual functions.
    • However, compilers normally automatically synthesizes a default destructor for every class if you don’t provide one.
    • Whenever this happens, this synthesized destructors quietly overrides the pure virtual destructor in the base class.
    • so, the derived classes remain concrete even without an explicit destructor to override the base class’s pure virtual destructor.
  • Reason for existance for pure virtual destructor:
    • The reason for existance for pure virtual destructor is to make the base class abstract when there is no other pure virtual function other than it in the base class.
  • Guideline:
    • Whenever you have virtual functions in your class, never forget to add virtual destructors even if they do nothing.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *