Effective C + + Learning NOTE clause 07: Declaring a virtual destructor for a polymorphic base class

Source: Internet
Author: User

C + + clearly states: when the derived class object is deleted by a base class pointer, and the base class takes a non-virtual destructor, the result is undefined-- The actual execution usually occurs when the derived component of the object is not destroyed! (Note: Using polymorphism in the way that a base class references a derived class, because a reference is simply a reference to the original object or an alias, it does not allocate memory, and the destruction of its reference object memory will be the responsibility of the original object, so when using the reference, if the destructor is not virtual, Then there will be no case of derived members being destroyed.

For example:

class Base{     Public:        Base(Const string&name): M_basename (name) {}Private:        stringm_basename;};classDerived Public Base{     Public: Derived (Const string& BaseName,Const string& Derivedname):Base(BaseName), M_derivedname (derivedname) {}Private:        stringm_derivedname;};
int Main (void) {    basenew derived ("base"  "derived");    delete pd;}

By GDB, a single-step debug found that when the delete PD, only the destructor of the base class was called, destroying the data members, but did not call the derived class's destructor, resulting in the data members of the derived class is not destroyed, resulting in a strange " partial Destruction " object. This can lead to resource leaks.

GDB debugs as follows:

Breakpoint1, Main () at Clause07_1.cpp: - -        Base*PD =NewDerived"Base","derived");(gdb) nDelete pd (GDB) sbase::~base (this=0x603070, __in_chrg=<optimized out>) at clause07_1.cpp:1111 Clas S base (GDB) Smain () at clause07_1.cpp:3232 }(GDB) s0x00007ffff752576d inch__libc_start_main () from/lib/x86_64-linux-gnu/libc.so.6

  Note: Using polymorphism in the way that a base class references a derived class, because the reference is only a reference to the original object or an alias, it does not allocate memory, and the destruction of its reference object memory will be the responsibility of the original object, so when using the reference, if the destructor is not virtual, Then there will be no case of derived members being destroyed.

  For example:

class Base{     Public:        ~Base() {cout<<"Base::~base"<<Endl; }        Virtual voidF1 () {cout<<"base::f1 ()"<<Endl; }        voidF2 () {cout<<"base::f2 ()"<<Endl; }};classDerived Public Base{     Public:        Virtual voidF1 () {cout<<"derived::f1 ()"<<Endl; }        voidF2 () {cout<<"derived::f2 ()"<<Endl; }        ~derived () {cout<<"derived::~derived ()"<<Endl; }};
int Main (void) {    derived D;     base &rd = D;    Rd.f1 ();    Rd.f2 ();}

The output is:

derived::f1 () Base : : F2 ()derived::  ~derived () base::~base

The destruction of derived is produced by destroying object D. Because Rd is only a reference and does not have its own memory, it does not need to be destroyed. There is no resource leak at this point ( the object referenced here is a static object, which is automatically destroyed ).

Second, for (1) The solution of the problem: give base Class A virtual destructor.

Simply define the destructor of the base class as virtual, as follows:

class Base {    public:        base(conststring& name): m_ BaseName (name) {}        virtual ~base() {}    private:         string m_basename;};

Thus, derived class's destructor, because of the inheritance of the reason, automatically into virtual, at this time, through the delete pointer, will trigger a polymorphic mechanism, because the pointer dynamic type is derived class, and the destructor of the derived class is a virtual function, So call the derived class destructor so that the data members of the derived class are destroyed, and when the derived class is finished, the destructor for the base class is automatically called, so there is no leakage of resources.

GDB Single-Step test certificate is as follows:

Breakpoint1, Main () at Clause07_2.cpp: to to        Base*PD =NewDerived"Base","derived");(gdb) n + delete pd; (GDB) sderived:: ~derived( This=0x603070, __in_chrg=<optimized out>) at Clause07_2.cpp: - -    classDerived Public Base(GDB) sderived::~derived ( This=0x603070, __in_chrg=<optimized out>) at Clause07_2.cpp: - -    classDerived Public Base(GDB) sBase::~base( This=0x603070, __in_chrg=<optimized out>) at Clause07_2.cpp: the the            Virtual~Base() {} (GDB) Smain () at Clause07_2.cpp: - -}

Third, any class as long as the virtual function is almost certain that there should also be a virtual destructor.

For example:

class Base{     Public:        Virtual voidF1 () {}};classDerived Public Base{     Public:        Virtual voidF1 () {ptr=operator New(sizeof(int)); }        ~derived () {delete ptr; }    Private:        void*ptr;};
int Main (void) {    basenew  derived ();    PD--F1 ();    Delete PD;}

The virtual function mechanism allocates memory for calling derived class functions and wants to be released in the destructor of the derived class, but because the destructor is not virtual, delete will only call the base class's destructor. So there's a memory leak!
The workaround is also that the base class destructor is defined as virtual so that it can take advantage of the polymorphic mechanism of the virtual function.

if base class does not contain a virtual function, it usually means that it is not intended to be used as a base class. when class does not attempt to be treated as a base class, making its destructor virtual is often a bad idea.

Because when a class has a virtual function, its memory layout will contain more than one vptr (virtual function table pointer), pointing to VTBL (vritual table). This causes the object to swell, and because other languages are not vptr, this results in no more portability.

For a class that inherits any destructor that is not virtual, a leak occurs if a polymorphic mechanism is used through the pointer, and the original derived object is destroyed by the deletion of the base type pointer to the derived type.

( note that by referencing the object's destruction, the object referenced by it is responsible for itself (the static object is automatically destroyed, the dynamically allocated need to delete PD (a pointer to the derived class);). But if you're going to use polymorphism, you might use a polymorphic way of using pointers, so it's a good idea to declare the destructor of the base class as virtual, as described in (1).

Vi. when you intend to use polymorphic, base class should generally have a virtual destructor. Also at this point, do not inherit the class that the destructor is not virtual. However, not all base classes are for polymorphism, and for situations where polymorphism is not intended, the base class does not require a virtual destructor.

Summarize

A. a base class with polymorphic properties should declare a virtual destructor.
B. If class has a virtual function, it should have a virtual destructor.
C. The design of a class is not intended to be used as a base class, or it should not be a virtual destructor for a base class design purpose other than for polymorphic purposes.

Effective C + + Learning NOTE clause 07: Declaring a virtual destructor for a polymorphic base class

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.