What happens to base class destructor if a derived class destructor throws an exception

后端 未结 3 1639
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-08 20:09

It just happened to me I wondered how resources are freed in the following case.

class Base {
  Resource *r;

public:
  Base() { /* ... */ }
  ~Base() {
             


        
相关标签:
3条回答
  • 2020-12-08 20:47

    According to §15.2/2:

    An object that is partially constructed or partially destroyed will have destructors executed for all of its fully constructed subobjects, that is, for subobjects for which the constructor has completed execution and the destructor has not yet begun execution.

    So the base class destructor should be called. That is, just like we know this will clean up the base class:

    #include <iostream>
    
    struct foo
    {
        ~foo()
        {
            std::cout << "clean" << std::endl;
        }
    };
    
    struct bar : foo
    {
        bar()
        { // foo is initialized...
            throw 0; // ...so its destructor is run
        }
    };
    
    int main()
    {
        try
        {
            bar b;
        }
        catch (...)
        {
            std::cerr << "caught" << std::endl;
        }
    }
    

    And that this will clean up the member:

    #include <iostream>
    
    struct foo
    {
        ~foo()
        {
            std::cout << "clean" << std::endl;
        }
    };
    
    struct bar
    {
        ~bar()
        { // f has been initialized...
            throw 0; // ...so its destructor will run
        }
    
        foo f;
    };
    
    int main()
    {
        try
        {
            bar b;
        }
        catch (...)
        {
            std::cerr << "caught" << std::endl;
        }
    }
    

    This will also clean up the base class:

    #include <iostream>
    
    struct foo
    {
        ~foo()
        {
            std::cout << "clean" << std::endl;
        }
    };
    
    struct bar : foo
    {
        ~bar()
        { // foo has been initialized...
            throw 0; // ...so its destructor will run
        }
    };
    
    int main()
    {
        try
        {
            bar b;
        }
        catch (...)
        {
            std::cerr << "caught" << std::endl;
        }
    }
    

    That's my understanding of the quote.

    0 讨论(0)
  • 2020-12-08 20:50

    The base destructor will get called.

    In Effective C++, Meyers recommends that exceptions shouldn't leave destructors. Catch the exception inside the destructor and handle it, swallow it or terminate.

    0 讨论(0)
  • 2020-12-08 21:12

    The base class destructor is indeed called. Sample code:

    #include 
    #include 
    
    class Base {
    public:
      Base() { /* ... */ }
      ~Base() {
        printf("Base\n");
      }
    };
    
    class Derived : public Base {
    public:
      Derived() { /* ... */ }
      ~Derived() {
        printf("Derived\n");
        throw 1;
      }
    };
    
    int main() {
      try {
        Derived d;
      } catch(...) {
        printf("CAUGHT!\n");
      }
    }
    

    This prints:

    Derived
    Base
    CAUGHT!
    
    0 讨论(0)
提交回复
热议问题