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

kum*_*mar 16 c++ constructor

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

fre*_*low 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

throwing in derived constructor
destroying base
Run Code Online (Sandbox Code Playgroud)

(请注意,本机指针的析构函数不执行任何操作,这就是为什么我们更喜欢RAII而不是原始指针.)

  • 这就是为什么把一个捕获并重新投入主要强制堆栈正确解开的原因. (3认同)

ybu*_*ill 9

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

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

class B : public A {
public:
    B() { throw 0; }
    ~B() {}
};
Run Code Online (Sandbox Code Playgroud)

调用~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) {}
};
Run Code Online (Sandbox Code Playgroud)

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


sbi*_*sbi 5

抛出异常时,将为其构造函数成功运行的所有(子)对象调用析构函数.这扩展到数据成员和基类.

例如,对于此代码

struct base {};

struct good {};

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

struct test : public base {
  std::string s;
  good g;
  bad b;
  test() {}
};
Run Code Online (Sandbox Code Playgroud)

之前test被执行的构造,第一基类的构造函数被调用,则该构造函数s,gb.只有这些成功完成,test才会执行构造函数.当异常的建设过程中引发的b,基类的构造函数以及构造函数的数据成员sg已全面执行,因此,它们的析构函数运行.test它本身的构造函数并b没有成功运行,因此它们的析构函数不会运行.


lia*_*iaK 5

来自标准文档,15.3 - 11,

所述的物体的完全构造基类和成员应被销毁进入一个构造或析构函数为该对象的功能块试戴的处理程序之前.