简体   繁体   中英

Default destructor in subclasses of base class with a virtual destructor

I have a base class A with a virtual destructor. A has descendants B and C which use the default destructor. Is it safe to delete an object of C through a pointer to A ?

More specifically, consider this sample code:

class A {
 public:
      A(){};
      virtual ~A() {/* code here */};
 };
 class B: public A {
      B() {/* code....*/};
      /* NO DESTRUCTOR SPECIFIED */
   };
 class C: public B {/*same as above, no destructor */};
 class D: public B {/* same as above, no destructor*/}

The code to be run looks something like this:

A* getAPointer(void); /* a function returning a C or a D*/
A* aptr=getAPointer();
/* aptr is declared as A*, but points to either an object of class C 
  or class D*/
delete aptr;

Is the delete aptr safe? Does it do the right thing: if aptr points to an object of class C , the aptr first calls C 's destructor, then B 's destructor, and finally A 's destructor ?

Is it safe to delete an object of C through a pointer to A?

Yes, it is totally safe as all the destructors in classes B , C and D will be implicitly virtual.

From:

15.4 Destructors [class.dtor]

10 A destructor can be declared virtual (13.3) or pure virtual (13.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined. If a class has a base class with a virtual destructor, its destructor (whether user- or implicitly-declared) is virtual.

As A has a virtual destructor, then B , and C , D respectively, have virtual destructors and:

delete aptr;

works correctly.

Yes, it's safe. Adding virtual to the destructors of your derived classes is redundant.

Consider how the mechanism works. When delete is used, the runtime needs to know with which destructor the destruction chain should begin. If the static type of the delete operand has a virtual destructor, then that's already sufficient for the runtime to know that it must take the extra trouble and inspect the dynamic type.

In your case, it finds that the dynamic type is C , so C::~C is called. C::~C automatically leads to B::~B and that one automatically leads to A::~A .

A requirement for C 's (or B 's) destructor to be virtual would be pointless. After all, the runtime has to find out the dynamic C type anyway if A::~A is virtual . At that point, it doesn't care whether C::~C is virtual or not. What difference would it make?

Is it safe to delete an object of C through a pointer to A ?

Yes. Since A 's destructor is virtual , C 's destructor will be called. This is simply due to how dynamic dispatch works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM