Question Le destructeur de la classe de base sera-t-il appelé si un objet lève une exception dans le constructeur?


Le destructeur de la classe de base sera-t-il appelé si un objet lève une exception dans le constructeur?


15
2017-09-21 10:11


origine


Réponses:


Si une exception est lancée pendant la construction, tous les sous-objets précédemment construits seront correctement détruits. Le programme suivant prouve que la base est définitivement détruite:

struct Base
{
    ~Base()
    {
        std::cout << "destroying base\n";
    }
};

struct Derived : Base
{
    Derived()
    {
        std::cout << "throwing in derived constructor\n";
        throw "ooops...";
    }
};

int main()
{
    try
    {
        Derived x;
    }
    catch (...)
    {
        throw;
    }
}

sortie:

throwing in derived constructor
destroying base

(Notez que le destructeur d'un pointeur natif ne fait rien, c'est pourquoi nous préférons le RAII aux pointeurs bruts.)


15
2017-09-21 10:15



Oui. La règle est que chaque objet dont le constructeur a terminé avec succès sera détruit à l’exception. Par exemple:

class A {
public:
    ~A() {}
};

class B : public A {
public:
    B() { throw 0; }
    ~B() {}
};

~ A () est appelé. ~ B () n'est pas appelé;

EDIT: de plus, supposons que vous ayez des membres:

struct A {
    A(bool t) { if(t) throw 0; }
    ~A() {}
};

struct B {
    A x, y, z;
    B() : x(false), y(true), z(false) {}
};

Ce qui se passe est: x est construit, y jette, x est détruit (mais ni y ni z).


9
2017-09-21 10:17



Lorsqu'une exception est levée, le les destructeurs sont appelés tout (sous-) objets dont les constructeurs ont été exécutés avec succès. Cela s'étend aux membres de données et aux classes de base.

Par exemple, pour ce code

struct base {};

struct good {};

struct bad {
  bad() {throw "frxgl!";}
};

struct test : public base {
  std::string s;
  good g;
  bad b;
  test() {}
};

avant testLe constructeur est exécuté, le constructeur de la classe de base est d'abord appelé, puis les constructeurs de s, g, et b. Seulement si ceux-ci finissent avec succès, le constructeur de test est exécuté. Lorsque l'exception est lancée pendant la construction de b, les constructeurs de classes de base ainsi que les constructeurs des membres de données s et g ont été entièrement exécutés, donc leurs destructeurs sont exécutés. Le constructeur de test lui-même et de b n'ont pas été exécutés avec succès, donc leurs destructeurs ne sont pas exécutés.


5
2017-09-21 10:26



De documents standard, 15.3 - 11,

le les classes de base entièrement construites et les membres d'un objet doivent être détruits avant d'entrer dans le gestionnaire d'une fonction   bloc d'un constructeur ou d'un destructeur pour cet objet.


4
2017-09-21 10:27