c++ - 派生类构造函数中的异常

标签 c++ exception inheritance constructor destructor

我在处理派生类中的构造函数异常时遇到一些问题。当派生类构造函数抛出错误,但父类已经分配了一些对象时。父类的析构函数会被调用吗?

示例:

class A
{
  A() { /* Allocate some stuff */ };

  virtual ~A() { /* Deallocate stuff */ };
};

class B : public A
{
  B() 
  { 
    /* Do some allocations */
    ...

    /* Something bad happened here */
    if (somethingBadHappened) 
    {
      /* Deallocate B Stuff */
      ...

      /* Throws the error */
      throw Error; /* Will A destructor be called? I know B destructor won't */
    };

  };

  ~B() { /* Deallocate B Stuff */ };
}

我想知道执行以下操作是否是个好主意:

B()
{ 
  /* Do some allocations */
  ...

  /* Something bad happened here */
  if (somethingBadHappened) 
  {
    /* Deallocate B Stuff */
    this->~B();

    /* Throws the error */
    throw Error; /* Will A destructor be called? I know B destructor won't */
  };
};

如果没有,做这些事情的正确方法是什么?

最佳答案

异常将导致堆栈展开到正确捕获异常的位置。这意味着抛出异常之前在范围内创建的任何对象都将被破坏,包括本例中的基类对象。

试试这个:

#include <iostream>

class A
{
public:
  A() { std::cout << "A::A()\n";}
  ~A() {std::cout << "A::~A()\n";}
};

class B : public A
{
public:
   B()
   {
      std::cout << "B::B()\n";
      throw 'c';
   }

   // note: a popular point of confusion -- 
   //   in this example, this object's destructor
   //   WILL NOT BE CALLED!
   ~B()
   {
      std::cout << "B::~B()\n";
   }
};


int main()
{
   try
   {
      B b;
   }

   catch(...)
   {
      std::cout << "Fin\n";
   }
   return 0;
}

输出应为:(注意 B::~B() 未调用)

A::A()
B::B()
A::~A()
Fin

只要您不尝试释放尚未分配的资源,按照您在问题中所示的方式手动调用析构函数就是安全的。最好将这些资源包装在某种类型的 RAII 容器中(std::auto_ptrboost::shared_ptr 等)以避免必要性调用析构函数。

Mooing Duck 提供了一个非常好的说明,说明当构造函数中抛出异常时堆栈展开如何工作:

Stack Unwinding during constructor exception

关于c++ - 派生类构造函数中的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7352833/

相关文章:

c++ - 为什么在 Windows 上没有微秒分辨率的 boost::date_time?

java - 为什么 `exception` 在任何地方都看不到?

c++ - Objective-C 在传递给 Swift 时释放 C++ 对象。我该如何防止这种情况?

java - 第二次加载时进度条失败

python - 获取对当前异常的引用

c++ - 为什么我不能将父类(super class)引用强制转换为也扩展另一个父类(super class)的子类?

Java:在跳过中间继承的父类(super class)时调用基父类(super class)方法

java - 在 Java 中获取参数化类的实例

c++ - 如何处理堆内存垃圾?

c++ - 如何检查文件是否存在于目录中?