Virtual Destructor

Base *b = new Derived();
// use b
delete b; // Here's the problem!
如果析構函數不是虛函數,則運行哪個析構函數是由該指針的類型決定的。如上例,若類Base的析構函數不是虛函數,而b指向的類型是派生類型的,此時delete b是undefined behaviour。
若果析構函數是虛函數,則運行哪個析構函數由該指針指向的對象的類型決定。如上例,若類Base的析構函數是虛函數,則delete b則調用Derived的析構函數。


一、http://www.programmerinterview.com/index.php/c-cplusplus/virtual-destructors/

Example without a Virtual Destructor:

#include iostream.h
class Base
{
   	public:
      	Base(){ cout<<"Constructing Base";}
      	
     // this is a destructor:
	
	~Base(){ cout<<"Destroying Base";}
};

class Derive: public Base
{
        public:
       	Derive(){ cout<<"Constructing Derive";}
       	
       	~Derive(){ cout<<"Destroying Derive";}
 };

void main()
{
    	Base *basePtr = new Derive();
        
        delete basePtr;
}


The output after running the code above would be:

Constructing Base  
Constructing Derive 
Destroying Base

Based on the output above, we can see that the constructors get called in the appropriate order when we create the Derive class object pointer in the main function.

But there is a major problem with the code above: the destructor for the "Derive" class does not get called at all when we delete ‘basePtr’.

So, how can we fix this problem?

Well, what we can do is make the base class destructor virtual, and that will ensure that the destructor for any class that derives from Base (in our case, its the "Derive" class) will be called.

Example with a Virtual Destructor:

So, the only thing we will need to change is the destructor in the Base class and here’s what it will look like – note that we highlighted the part of the code where the virtual keyword has been added in red:

class Base
{
   	public:
      	Base(){ cout<<"Constructing Base";}

	// this is a virtual destructor:
	virtual ~Base(){ cout<<"Destroying Base";}
};

Now, with that change, the output after running the code above will be:

Constructing Base  
Constructing Derive 
Destroying Derive
Destroying Base

Note that the derived class destructor will be called before the base class.

So, now you’ve seen why we need virtual destructors and also how they work.

One important design paradigm of class design is that if a class has one or more virtual functions, then that class should also have a virtual destructor.

二、http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors

Virtual destructors are useful when you can delete an instance of a derived class through a pointer to base class:

class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
}

Here, you'll notice that I didn't declare Base's destructor to be virtual. Now, let's have a look at the following snippet:

Base *b = new Derived();
// use b
delete b; // Here's the problem!

Since Base's destructor is not virtual and b is a Base* pointing to a Derived object, delete bhas undefined behaviour. In most implementations, the call to the destructor will be resolved like any non-virtual code, meaning that the destructor of the base class will be called but not the one of the derived class, resulting in resources leak.


發佈了49 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章