Search

12.3 — Virtual destructors, virtual assignment, and overriding virtualization

Virtual destructors

Although C++ provides a default destructor for your classes if you do not provide one yourself, it is sometimes the case that you will want to provide your own destructor (particularly if the class needs to deallocate memory). You should always make your destructors virtual if you’re dealing with inheritance. Consider the following example:

Because base is a Base pointer, when base is deleted, the program looks to see if the Base destructor is virtual. It’s not, so it assumes it only needs to call the Base destructor. We can see this in the fact that the above example prints:

Calling ~Base()

However, we really want the delete function to call Derived’s destructor (which will call Base’s destructor in turn), otherwise m_array will not be deleted. We do this by making Base’s destructor virtual:

Now this program produces the following result:

Calling ~Derived()
Calling ~Base()

Rule: Whenever you are dealing with inheritance, you should make any explicit destructors virtual.

Virtual assignment

It is possible to make the assignment operator virtual. However, unlike the destructor case where virtualization is always a good idea, virtualizing the assignment operator really opens up a bag full of worms and gets into some advanced topics outside of the scope of this tutorial. Consequently, we are going to recommend you leave your assignments non-virtual for now, in the interest of simplicity.

Ignoring virtualization

Very rarely you may want to ignore the virtualization of a function. For example, consider the following code:

There may be cases where you want a Base pointer to a Derived object to call Base::getName() instead of Derived::getName(). To do so, simply use the scope resolution operator:

You probably won’t use this very often, but it’s good to know it’s at least possible.

12.4 -- Early binding and late binding
Index
12.2a -- The override and final specifiers, and covariant return types

26 comments to 12.3 — Virtual destructors, virtual assignment, and overriding virtualization

  • Kinten

    I understood it, but I get the feeling that I will forget it really soon, maybe some practice is needed :[
    Well explained, thx

  • Lee

    HI,

    I want to call a derived class function, that isn’t defined in the base class, using base class pointers. but this always raises the error:

    error C2039: ‘derivedFunctionName’ : is not a member of ‘BaseClass’

    Do you know how i could get around this?

    Thanks,

    Lee.

    • Add a virtual function of the same name into the base class. You can define the base-class function with an empty body, or even better, make it a pure virtual (abstract) function.

  • Lion

    Really rocking and mind blowing explanation.:D

    Thanks a lot Alex.

  • Sakthi

    Hello Alex,
    I assume you must have overloaded the new, delete and paranthesis operators. Could you show the code for this ?
    If not then HOW do these operators work with classes ‘Derived’ and ‘Base’ ?
    new int[5] makes sense. but new Derived(5) does not .
    This is driving me nuts. Please help.

  • pranesh

    please have a look at the following code :

    Now this program produces the following result:

    Calling ~Derived()
    Calling ~Base()

    i am unable to understand why ‘calling ~Base()’ is been printed here?
    when we reached delete pbase; in int main() it goes to Base class first and finds that its destructor is virtual so it goes to Derive class and finds another destructor and executes it but why does it prints ~Base() in any case?

    • jason

      i’m also stuck in the same question!may be when derivative destructor is called,then the cursor returns to base for executing line 31 but it should again call derived destructor as again it will come across the virtual base destructor! someone help please!

    • Gigwig

      That is the thing with Inheritance, constructors are called, by default, from the base class to the derived class and the destructors run from the derived class to the base class.

      • Alex

        Exactly this. Constructors execute in order from the most-base to most-derived class. Destructors execute in order from most-derived to most-base class.

        If the Base destructor was not virtual, then as far as base knows, Base is the most derived class, so only the ~Base constructor would execute. However, since the Base destructor is virtualized, base knows that there’s a Derived destructor. Consequently, ~Derived executes first, and then ~Base executes second.

  • Devashish

    Some confusions:

    “When a variable goes out of scope, or a dynamically allocated variable is explicitly deleted using the delete keyword, the class destructor is called (if it exists) to help clean up the class before it is removed from memory” from 8.6 Destructors.

    It might seem stupid, but my question is that why Destructor of Derived isn’t called here? The class Derived also have a destructor. ~Base is called when we delete pBase. But, according to previous lessons, there is another case where destructors are called that is, when a variable of that class goes out of scope. At the end of main, pDerived is going out of scope, but ~Derived is not called. Why…??? If I remove this line: delete pBase; from the code above, nothing is called when variables go out of scope.I found an interesting fact, that destructors aren’t called when variables are pointers that points to an object. Am I right???

    • Alex

      When a pointer goes out of scope, the object it is pointing to is not destroyed.

      In the example above, when you delete pBase, the Derived constructor will be called if the destructors have been properly virtualized.

  • Devashish

    Stack overflow cleared some confusions. Pointers aren’t instances. They only hold address of an instance of same type. If pointer is assigned a dynamically allocated instance, when its block ends, pointer gets destroyed and that causes a memory leak. And because pointers aren’t instances, destructor isn’t called when it goes out of scope.

  • Night Owl

    I am a bit confused why you had to dynamically allocate pDerived, if the Derived constructor dynamically allocates an array. Is there a relationship between them at all?

    Since you deleted pBase, consequently deleting the address that both pBase and pDerived was pointing to, are both of them now pointing to nothing? Would setting those pointers to null be necessary in this case?

    • Alex

      There’s no relationship between dynamically allocating pDerived and the fact that Derived objects dynamically allocate an array themselves.

      Deleting a pointer doesn’t cause the value that the pointer holds to change. The pointer is left holding the address of memory that has been deallocated (making it a hanging pointer). Using such a pointer is dangerous.

      Normally you’d want to set the value of a pointer that has been deleted to null, but in this case since the program terminates anyways immediately afterward, it’s not necessary.

  • jonas

    int main()
    {
        Derived *pDerived = new Derived(5);
        Base *pBase = pDerived;
        delete pBase;

        return 0;
    }
    Does pBase point to the same location as pDerived now here? And does deleting pBase dealocate the pDerived itself(since ~Derived() just dealocate m_pnArray)?

    • Alex

      Yes, pBase and pDerived will hold the same address (of the instanted Derived object).
      Deleteing pBase will deallocate the derived object properly if the Base destructor is properly virtual. If the Base destructor is not virtual, then only the Base portion of the class will be deleted (causing a memory leak).

  • Thanks for this helpful site, Alex, a colon is missing after public at the last example.

  • Ramkrushna Joshi

    Hi alex,one question…

    int main()
    {
        Derived *pDerived = new Derived(5);
        Base *pBase = pDerived;
        delete pBase;

        return 0;
    }
    in this you have deleted pBase,but if we delete pDerived then without virualization of Base destructor,both destructor will be called.
    So my question is cann’t we delete  pDerived…??yes then why need to delete pBase…??

    • Alex

      Yes, of course you can delete pDerived. But there are legitimate cases where you will only have a pointer to the base class. We explore some of those cases in future lessons. This is just setting up the foundation for further understanding.

  • Darren

    Just when I think I’ve got a reasonable handle on the language along comes a curve ball about virtual assignment operators - what on earth? I’m going to guess based on the information I have on the virtual keyword when used with member functions. A virtual assignment operator probably calls the most-derived assignment operator in an inheritance chain meaning that you only change the most derived part of an object rather than changing an object in its entirety? Sounds sensible if the object is large. Am I anywhere near?

    • Alex

      Typically, a derived assignment operator will call the base-assignment operator to copy the base portion of the class before it copies the derived portion itself (because, after all, if you’re copying a derived object, you want the whole thing, not just the derived portion). This is analogous to how a derived class constructor will call a base class constructor to initialize the base portion of the object before initializing the derived portion.

      Note that typically the parameter for an assignment operator is a reference to an object of the class itself: this means a base class assignment operator will take a base object, and a derived class assignment operator will take a derived object. This gives these functions different signatures, and the compiler will treat them as distinct. So virtualization doesn’t actually help you here.

      Virtualized assignment operators could really be an entire lesson in and of itself. It’s complicated, and has a lot of edge cases to consider.

      • Darren

        I think with a lot of the advanced features of C++ its good to know they exist and have a gist of what they do but unless you’re actually going to use them a full understanding probably isn’t necessary. And when you say "has a lot of edge cases" I hear "lots of potential for causing debugging misery".

  • Don jose

    Hi Alex,

    I am not getting why my destructors getting called two times
    the code is below

    Output is:
    Derived
    Base
    Derived
    Base
    (Using code block compiler)

    Thnaks in advance.. Great tutorial ever

    • Alex

      When you delete ptr, contents that ptr are pointing to are being destroyed, which calls the destructor.
      Then when D1 goes out of scope, it gets destroyed, which also calls the destructor.

      In this particular case, this will cause problems because ptr points to D1, so the same thing is getting deleted twice. You should generally only delete a pointer if you’ve allocated memory for it using new -- which you haven’t done here.

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter