如果对象在构造函数中抛出异常,是否会调用基类的析构函数?

时间:2010-09-21 10:11:44

标签: c++ constructor

如果对象在构造函数中抛出异常,是否会调用基类的析构函数?

4 个答案:

答案 0 :(得分:17)

如果在构造期间抛出异常,则将正确销毁所有先前构建的子对象。以下程序证明基础肯定被破坏了:

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;
    }
}

输出:

throwing in derived constructor
destroying base

(注意本机指针的析构函数什么也不做,这就是为什么我们更喜欢RAII而不是原始指针。)

答案 1 :(得分:9)

是。规则是构造函数成功完成的每个对象都将在异常时被破坏。 E.g:

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

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

~A()。 〜B()未被调用;

编辑:此外,假设您有成员:

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

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

会发生什么:x被构造,y被抛出,x被破坏(但是y和z都没有)。

答案 2 :(得分:5)

当抛出异常时, 析构函数被调用 所有(子) 对象,其构造函数已成功运行 < / strong>即可。这扩展到数据成员和基类。

例如,对于此代码

struct base {};

struct good {};

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

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

test的构造函数执行之前,首先调用基类的构造函数,然后调用sgb的构造函数。只有这些成功完成,才会执行test的构造函数。在构造b期间抛出异常时,基类构造函数以及数据成员sg的构造函数已完全执行,因此它们的析构函数将被运行。 test本身和b的构造函数尚未成功运行,因此它们的析构函数不会运行。

答案 3 :(得分:5)

从标准文档 15.3 - 11

  

完全构造的基类和对象的成员应该在进入函数的处理程序之前销毁   该对象的构造函数或析构函数的块。