18.4 — 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:

Note: If you compile the above example, your compiler may warn you about the non-virtual destructor (which is intentional for this example). You may need to disable the compiler flag that treats warnings as errors to proceed.

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.

As with normal virtual member functions, if a base class function is virtual, all derived overrides will be considered virtual regardless of whether they are specified as such. It is not necessary to create an empty derived class destructor just to mark it as 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.

Should we make all destructors virtual?

This is a common question asked by new programmers. As noted in the top example, if the base class destructor isn’t marked as virtual, then the program is at risk for leaking memory if a programmer later deletes a base class pointer that is pointing to a derived object. One way to avoid this is to mark all your destructors as virtual. But should you?

It’s easy to say yes, so that way you can later use any class as a base class -- but there’s a performance penalty for doing so (a virtual pointer added to every instance of your class). So you have to balance that cost, as well as your intent.

Conventional wisdom (as initially put forth by Herb Sutter, a highly regarded C++ guru) has suggested avoiding the non-virtual destructor memory leak situation as follows, “A base class destructor should be either public and virtual, or protected and nonvirtual.” A class with a protected destructor can’t be deleted via a pointer, thus preventing the accidental deleting of a derived class through a base pointer when the base class has a non-virtual destructor. Unfortunately, this also means the base class can’t be deleted through a base class pointer, which essentially means the class can’t be dynamically allocated or deleted except by a derived class. This also precludes using smart pointers (such as std::unique_ptr and std::shared_ptr) for such classes, which limits the usefulness of that rule (we cover smart pointers in a later chapter). It also means the base class can’t be allocated on the stack. That’s a pretty heavy set of penalties.

Now that the final specifier has been introduced into the language, our recommendations are as follows:

  • If you intend your class to be inherited from, make sure your destructor is virtual.
  • If you do not intend your class to be inherited from, mark your class as final. This will prevent other classes from inheriting from it in the first place, without imposing any other use restrictions on the class itself.

18.5 -- Early binding and late binding
18.3 -- The override and final specifiers, and covariant return types

111 comments to 18.4 — Virtual destructors, virtual assignment, and overriding virtualization

  • Nirbhay


    What is happening in the following code from the first example??
    Why is the 'derived' pointer assigned to 'base' pointer?

  • Anthony

    Hi Alex,

    I'm getting the following warning if I don't explicitly put in an empty virtual destructor:

    ||=== Build: Debug in test (compiler: GNU GCC Compiler) ===|
    C:\Users\Anthony\Documents\CodeBlocks\C++\test\main.cpp|5|warning: 'class Animal' has virtual functions and accessible non-virtual destructor [-Wnon-virtual-dtor]|
    C:\Users\Anthony\Documents\CodeBlocks\C++\test\main.cpp|17|warning: base class 'class Animal' has accessible non-virtual destructor [-Wnon-virtual-dtor]|
    ||=== Build finished: 0 error(s), 2 warning(s) (0 minute(s), 0 second(s)) ===|

    What should I do?

  • solaris

    Hi Alex,In case of instantiating new object from another class how the dynamic memory should be handled? please have a look in below code:
    "mychart" is an object (with dynamic allocation) of class "chart" (note: chart class is derived from Base class)and inside chart class I have instantiated an object of "Base" class (again in dynamic allocation).
    how should the destructor of "Base" and "Chart" be written in order not to have memory leak?

    Base class:

    chart class:


    • if @chart is a @Base, it shouldn't allocate a @Base at all, it already has all of @Base's functionality.
      For other cases, every class should free the memory that it allocated.

      • solaris

        thanks! my mistake! Base is not directly inherited by chart.(in general suppose it is a chain of inherited classes, in that case how the root class be designed for best memory management)

  • David

    Hi Alex! Thanks for the tutorial.
    I believe this is a typo:

    "This also precludes using smart points (such as std::unique_ptr and std::shared_ptr) for such classes,"

    It says "smart points" rather than "smart pointers"

  • in the sentence "Unfortunately, this also means the base class can’t be deleted through a base class pointer" does that mean
    we won't be able to allocate a base object on the stack too since destructor is protected, correct ?
    we will not be able to use base alone at all, we have to use derived whether for automatic or dynamic allocation.

  • Nick

    Hey Alex,

    These tutorials are an absolute masterpiece!

    I have a question please - are implicit (non declared) destructors implicitly virtualized? So say in the above examples that you did not explicitly declare the destructors for Base and Derived, and you called delete base. Would the Derived destructor be called automatically? Many thanks!

    • If you don't define a destructor then the class has none.

      • Nick

        Thanks for getting back to me nascardriver!

        Ah, I had thought that, analogous to constructors, an implicit destructor would be provided (to destroy objects of the class once they go out of scope) if we don't provide one. In the lesson on destructors - "there are few cases where you would need to explicitly declare a destructor", I had always thought this to mean C++ automatically generated one as objects of the class go out of scope?

        • Whoops, yeah, it's even the first sentence of this lesson. It's not virtual though.

          • Nick

            Thanks NascarDriver! So if implicit destructors aren't virtual, then

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

            Can we go further to say that one should make ALL destructors virtual in the context of inheritance? If so, isn't that a little bit of a pain (we have to explicitly declare a destructor for each of our (base and inherited) classes, because that is the only way we can make the destructors virtual).

            • > one should make ALL destructors virtual in the context of inheritance?
              That's how I do it, so I'll go with yes. @Alex might have a different opinion, let's see.

              • Nick

                Cheers Nascardriver ( if that's how you do it, then it's more than good enough for me!). Thank you both for the upkeep of this fine website. Best wishes from London

              • Alex

                If a base class destructor is virtual, all derived class destructors will be virtual, even if not explicitly specified as such. If you do explicitly define a derived class destructor, mark it as virtual (since that's what it is). But it's not necessary to create a derived class destructor just to mark it as virtual (e.g. if it has an empty body).

                As for base class destructors, whether to make them virtual or not is a hard question -- it's easy to say yes, so that way you can use any class as a base class, but there's a performance penalty for doing so (a virtual pointer added to every instance of your class). So you have to balance that cost.

                Herb Sutter (a highly regarded C++ guru) suggests, "A base class destructor should be either public and virtual, or protected and nonvirtual."

                A class with a protected destructor can't be deleted via a pointer, thus preventing the accidental deleting of a derived class through a base pointer when the base class has a non-virtual destructor. Unfortunately, this also means the base class can't be deleted through a base class pointer, which essentially means the class can't be dynamically allocated except by a derived class. This precludes using std::unique_ptr and std::shared_ptr for such classes, which limits the usefulness of that rule.

                I think a better answer may be to define your destructors as virtual, or mark your class as final, so it can't be inherited from.


                • Paragraph 1: I agree. I like writing down destructors when I first write the class, even if the destructor is empty. That way, if I decide that I need a destructor later on, I don't have to check if this class is virtual. When I'm done with the project and encounter an empty destructor I'll remove it. This is personal preference, your suggestions sounds better, I guess I'll go with that from now on.

                  Paragraph 2: Agreed.

                  Paragraph 3, 4: This is shooting oneself in the foot. Unless the project is required to analyze real time data or similar, the effort and problems caused by this aren't worth it in my opinion.

                  Paragraph 5: I like that.

                  If you're planning on including your comment in the lesson:
                  * In paragraph 1 you wrote "constructor" in place of "destructor"
                  * Paragraph 5 is missing a comma or "to" after "may be" and an "in the context of inheritance" or similar, to prevent people from declaring all destructors virtual.

  • Rev

    So, Mr. Alex, or any other respectable admin, I have an extremely silly question to ask. I define 3 classes like this:

    And i create a reference of an A object which refers to a C

    So, if i want it to print "C class", i use a.print(), or a::A.print() for "A class". But what if i want to print "B class", and still can print "C class" easily? Obviously C is inherited from B, so there should be a way to do that, right?
    I attempted to do this

    and it says:
    `B' is not a base of `A'

    • nascardriver

      Hi Rev!

      @a doesn't know what it is, apart from being some child of @A or an @A itself.
      You can use @C's functions, because @a has @C's VTable and you can use @A's functions, because @a is a child of @A.
      You cannot directly call @B's functions, because an @A reference isn't necessarily a @B.

      If you want to call @B's functions on @a you need to cast @a to a @B reference using a @dynamic_cast. A @dynamic_cast performs a run-time check to make sure the types are compatible.

  • Lim Che Ling

    Having these 2 rules in mind (Rule 1: Whenever you are dealing with inheritance, you should make any explicit destructors virtual. Rule 2"you should only make your destructor virtual if you have some other virtual function in the class".) and look at the following example which all 4 cases fulfil these 2 rules but only in case 4, virtual destructor is needed. Am I right to conclude that only in case 4 virtual destructor is necessary (not case 1 to 3)?  

    #include <iostream>
    class Base
        virtual const char* getName(int x) { return "Base getName()";}
         ~Base(){ std::cout << "~Base.\n";}

    class Derived : public Base
        virtual const char* getName(int x) { return "Derived getName()";}
        ~Derived(){ std::cout << "~Derived.\n";}

    int main()
        //Case 1: No need virtual destructor
        /*Derived derived;
        Base &rBase = derived;
        std::cout << rBase.getName(1) << '\n';
        //Case 2: No need virtual destructor
        /*Derived derived;
        Base *bPtr = &derived;
        std::cout << bPtr->getName(2) << '\n';*/
        //Case 3: No need virtual destructor
        /*Derived *ptr = new Derived();
        std::cout << ptr->getName(2) << '\n';
        delete ptr;*/
        //Case 4: Need virtual destructor
        Base *bPtr = new Derived();
        std::cout << bPtr->getName(2) << '\n';
        delete bPtr;

        return 0;

    • Alex

      No. The rules as stated apply to class definitions, not the code that uses the classes. Since your Base() class has a virtual function (getName()), the Base destructor should also be virtual.

  • Gery

    Hi Alex Thanks for such a useful website. Will u please explain how VTable set pointers to function in case of virtual destructor I mean the flow of it just like u explained in case of virtual constructor using table.

  • i do this and it work
    is that right

  • Mr C++

    Alex, Will Virtual Assignment be taught in the future lessons/chapters?

  • C++ Learner

    Hi, why there is a destructor but not constructor? I mean in this example destructor is called but there is no constructor called

  • sarvesh

    Which destructor should be virtual here ? It is base class destructor.
    Comment added in code section is not correct
    virtual ~Derived() // note: virtual
    ~Derived() // note: not virtual

    You have to move these both comments to base class destructor.

  • Tim Hothersall

    It did not take a great deal of time for my to understand the basic principle of polymorphism, but I had a hell of a job justifying it and understanding its full potential.  Inheritance I use all the time, but it took about 8 months for me to use polymorphism in a meaningful way.

    Although I am far from experienced, I have noted that there seems to be a tendency for programmers to use functionality because it is there rather than because it is beneficial to the program. Maybe I am wrong to think like this; I don't know, but I try to only use things that are helpful. (using the right tool for the right job rather than using a sledgehammer to crack a nut).

    One thing that I didn't realise and why it took me so long to find polymorphism useful is that calling a virtual function within a method in a base class will jump to the derived version of the function if there is one.  Looking back over this tutorial now, I can see that this is explained, but I just didn't see it for some reason.

    • Alex

      Yup. Virtual functions are fantastic, but only for solving particular types of problems. For other kinds of problems, other tools are more appropriate. As you say, use the right tool for the job at hand.

  • First, Thanks for replying quickly on comments :)

    I don't understand the part with deleting that calls the base portion destructor of a derived class, when the destructor is not virtual... What happens with the derived part of the object, it gets deleted too with some default destructor or remains as garbage in memory?? If it remains, we could point to it and use non-inherited members and functionality with undefined results, so I guess that must be false...

    • Alex

      If you have an object of a derived class, and your base class destructor isn't virtual, and you delete a pointer to the base portion of that class, only the base portion of the class gets deleted. The derived portion stays in memory with no way to get to it, so that memory is leaked/lost until your program is terminated and the operating system cleans up.

  • Mario

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

    Is there any reason to not make any destructors virtual ever? Or can I safely make every destructor I write virtual?

    Regards :)

    • Alex

      > Is there any reason to not make any destructors virtual ever? Or can I safely make every destructor I write virtual?

      In general, you should only make your destructor virtual if you have some other virtual function in the class. As soon as you add any virtual functions, every object of your class now needs a symbol table, which means you've increased the size of your class objects by a pointer, and made them slightly less efficient (it takes longer to call a virtual function than a non-virtual one). Why pay this performance penalty unless you're actually using virtual functions for their intended purpose?

  • Sam

    line 22 in the second code block: wrong commentary

  • Don jose

    Hi Alex,

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

    Output is:
    (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.

  • 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".

  • 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.

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

  • 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).

  • 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.

  • 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.

  • 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. Only the pointer (holding the address of the object) is destroyed.

      To destroy the object itself, you have to use delete.

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

  • 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.

  • 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.

  • Lion

    Really rocking and mind blowing explanation.:D

    Thanks a lot Alex.

  • Lee


    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?



    • 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.

  • Kinten

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

Leave a Comment

Put all code inside code tags: [code]your code here[/code]