Why base class destructor (virtual) is called when a derived class object is deleted?

后端 未结 7 791
再見小時候
再見小時候 2020-12-13 13:45

A difference between a destructor (of course also the constructor) and other member functions is that, if a regular member function has a body at the derived class, only the

相关标签:
7条回答
  • 2020-12-13 14:17

    This is by design. The destructor on the base class must be called in order for it to release its resources. Rule of thumb is that a derived class should only clean up its own resources and leave the base class to clean up itself.

    From C++ spec:

    After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2).

    Also, because there is only one destructor, there is no ambiguity as to which destructor a class must call. This is not the case for constructors, where a programmer must pick which base class constructor should be called if there isn't an accessible default constructor.

    0 讨论(0)
  • 2020-12-13 14:17

    A base class destructor may be responsible for cleaning up resources that were allocated by the base class constructor.

    If your base class has a default constructor (one that doesn't take parameters or has defaults for all its parameters) that constructor is automatically called upon construction of a derived instance.

    If your base class has a constructor that requires parameters, you must call it manually in the initializer list of the derived class constructor.

    Your base class destructor will always be automatically called upon deletion of the derived instance since destructors don't take parameters.

    If you're using polymorphism and your derived instance is pointed to by a base class pointer, then the derived class destructor is only called if the base destructor is virtual.

    0 讨论(0)
  • 2020-12-13 14:23

    Because that's how dtor's work. When you create an object, ctors are invoked starting from the base, and going all the way to the most derived. When you destroy objects (correctly) the reverse happens. The time that making a dtor virtual makes a difference is if/when you destroy an object via a pointer (or reference, though that's fairly unusual) to the base type. In that case, the alternative isn't really that only the derived dtor gets invoked -- rather, the alternative is simply undefined behavior. That make happen to take the form of invoking only the derived dtor, but it might take an entirely different form as well.

    0 讨论(0)
  • 2020-12-13 14:26

    As Igor says constructors must be called for base classes. Consider what would happen if it wouldn't be called:

    struct A {
        std::string s;
        virtual ~A() {}
    };
    
    struct B : A {};
    

    If the destructor for A would not be called when deleting a B instance, A would never be cleaned up.

    0 讨论(0)
  • 2020-12-13 14:31

    The Standard says

    After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant members,the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2). A return statement (6.6.3) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called. Destructors for elements of an array are called in reverse order of their construction (see 12.6).

    Also as per RAII resources need to be tied to the lifespan of suitable objects and the destructors of respective classes must be called upon to release the resources.

    For example the following code leaks memory.

     struct Base
     {
           int *p;
            Base():p(new int){}
           ~Base(){ delete p; } //has to be virtual
     };
    
     struct Derived :Base
     {
           int *d;
           Derived():Base(),d(new int){}
           ~Derived(){delete d;}
     };
    
     int main()
     {
         Base *base=new Derived();
         //do something
    
         delete base;   //Oops!! ~Base() gets called(=>Memory Leak).
     }
    
    0 讨论(0)
  • 2020-12-13 14:37

    When any object is destroyed, destructors run for all sub-objects. This includes both reuse by containment and reuse by inheritance.

    0 讨论(0)
提交回复
热议问题