Override Destructor C ++

From the C ++ FAQ:

[11.4] Is it possible to overload the destructor for my class? Not.

I understand this means that you cannot change the return type, argument types and number of arguments. I can split my hair into word syntax, but is it possible to override the parent destructor?

class Child : public Parent { public: virtual Parent::~Parent() { // New definition } }; 

And in this case recursively?

 class Grandchild : public Child { public: Child::Parent::~Parent() { // An even newer definition } }; 

I read this and related post , and it makes me think, because destructors are not inherited, they cannot be overridden, but I have never seen this explicitly stated.

EDIT: I modified this to reflect the fact that I want to override the parent destructor, pay attention to Child and Grandchild overriding ~ Parent ().

The main reason I do this is to maintain the parent interface by changing the way it is destroyed (all the reason for the child class). I will have something else governing everything the parent has created, and I will explicitly call their destructors at a later time of my choice.

+7
source share
4 answers

I can split the hair into the syntax of words

No, you definitely aren't - these are two different things.

but is it possible to override the destructor?

Yes, and in fact you have to do this in many cases. For this to work for a polymorphic object, you need to declare the base class destructor as virtual , though:

 Parent const& p = Child(); 

It will correctly call p.~Child() at the end of the scope because Parent::~Parent is virtual.

+8
source

Yes, you can override the class destructor. In fact, when you define a class hierarchy that uses polymorphism, you must declare a virtual destructor in the base class.

Overrides of destructors work just like overrides of normal member functions work in that when you destroy an object by deleting an object through a pointer to the base class, the destructor of the derived class is correctly called. This is why you must have a virtual destructor in the base class for polymorphic hierarchies.

However, there is a difference between virtual destructors and virtual member elements that have nothing to do with the nature of the virtual destructor. That is, when executing the code:

 class A { public: virtual void Foo() {} virtual ~A() {}; }; class B : public A { public: void Foo() {}; ~B() {} }; int main() { A* a = new B; a->Foo(); // B::Foo() is called delete a; // B is destroyed via B::~B() } 

... when you call a->Foo() , the Foo() method in B called. Since B::Foo() does not explicitly call A::Foo() , A::Foo() not called.

However, when an object is destroyed through delete a; , first the destructor B::~B() is called, and then after that it ends, but before the control returns to the program, the base class destructor A::~A() also called.

Of course, this is obvious when you think about it, and again it has nothing to do with the nature of the virtual destructor, but it behaves differently than the usual call to the virtual method, so I thought d specify this.

Mandatory standard quotation:

[C ++ 03] 12.4 / 6: Destructors

After executing the body of the destructor and destroying any automatic objects allocated inside the body, the destructor for class X calls destructors for direct elements of Xs, destructors for Xs direct base classes and, if X is the type of the derived class itself (12.6.2), its destructor calls destructors for virtual base Xs classes. All destructors are invoked as if they referred to a qualified name, that is, they ignored any possible virtual redefinition of destructors in more derived classes. Foundations and members are destroyed in the reverse order of completion of their constructor (see 12.6.2). The return statement (6.6.3) in the destructor cannot directly return to the caller; before transferring control to the caller, destructors for members and bases are called. Destructors for array elements are called in the reverse order of their construction (see 12.6).

+4
source

Yes: you may have virtual destructors, and the only reason is to override them in derived classes.

It looks like this:

 class Parent { public: virtual ~Parent(); }; class Child : public Parent { public: virtual ~Child(); }; class Grandchild : public Child { public: ~Grandchild(); // virtual is inherited here }; 

Note that the destructor is not overridden by the name, just like ordinary functions, because the name always refers to the class whose instance you are destroying.

Please also note that destructors of the parent class are also always called, so you do not need to duplicate their cleanup code: read the information about the object of the object and the structure of the subclass of the base class and the destruction order for details.


Terminology

  • overriding a function means implementing a function of the virtual base class in a derived class. You cannot change the signature at all (except for using covariant return types). Thus, an override always has the same signature as an inherited virtual function.
  • function overloading means the implementation of several functions with the same name (and in a sense the same area). Thus, congestion always has a different signature for others with the same name, does not apply directly to virtual dispatch, and is not necessarily inherited.
+3
source

Yes; you can and should make a virtual destructor whenever you have a child class that can be destroyed using a reference to the base class. Static code analysis tools will even complain if you don't offer a virtual destructor.

Consider the following example:

 class A { public: A() { a = new int; } virtual ~A() { delete a; } private: int *a; }; class B : public A { public: B() { b = new int; } virtual ~B() { delete b; } private: int *b; }; int main() { A *a = new B(); delete a; } 

If the destructor was not virtual, then delete a will only call the destructor, and you will end the memory leak. But since it is virtual, both destructors will be called in the order ~B()~A() .

0
source

All Articles