类的构造函数中的异常处理行为

时间:2014-10-07 06:18:24

标签: c++ exception-handling

我有这个程序,派生类的ctor抛出异常。该程序只是一个示例程序,我只是想了解异常处理的概念。

class A{
public:
   A() {}

   ~A(){std::cout << "DTOR called - A!!" << std::endl;}
};

class B : public A
{
public:
   B():A()
   {
      try
      {
         init();
      }
      catch(...)
      {
         std::cout << "Inside catch block in B's Ctor!!" << std::endl;
         throw this;
      }
   }

   void init() { throw 0;  }

   ~B() {std::cout << "DTOR called - B!!" << std::endl; }
};

int main()
{
   try{
      B *b = new B;

      std::cout << "Äfter B's ctor called in try block!!" << std::endl;
      delete b;
      std::cout << "Äfter B's dtor called in try block!!" << std::endl;
   }

   catch(B* b)
   {
      delete b;
      b = NULL;
      std::cout << "Exception Occurred in B!!" << std::endl;
   }

   catch(A* a)
   {
      delete a;
      a = NULL;
      std::cout << "Exception Occurred in A!!" << std::endl;
   }

   catch(...)
   {
      std::cout << "Exception Occured!!" << std::endl;
   }
   return EXIT_SUCCESS;
}

预期的输出是它应该进入B的捕获块,并且应该调用第一个B的dtor,然后是A的dtor。但上述程序的输出是:

Inside catch block in B's Ctor!!
DTOR called - A!!
DTOR called - B!!
DTOR called - A!!
Exception Occurred in B!!

这里我的问题是为什么A类的dtor在只进入B类的catch块并且只调用B类的dtor时才调用两次? 还请告诉我这里是否犯了一些错误。 任何帮助表示赞赏

编辑:

class B : public A
{
public:
   B():A()
   {
      try
      {
         szName = new char[100];
         init();
      }
      catch(...)
      {
         std::cout << "Inside catch block in B's Ctor!!" << std::endl;
         throw this;
      }
   }

   void init() { throw 0;  }

   ~B()
   {
      delete szName;
      std::cout << "DTOR called - B!!" << std::endl;
   }

   char *szName;
};

这里我在类B中创建了一个char指针。在抛出异常之前,在Ctor中的try块中分配了内存。现在在这种情况下,如果我没有捕获B类的异常

,就会出现内存泄漏

4 个答案:

答案 0 :(得分:3)

你为什么要扔#34;这个&#34;在你的拦截块?你试图制作&#34;这已经bar#34;所以你怎么能扔掉它?尝试扔你抓到的东西,或其他东西,比如&#34;糟糕&#34;。

答案 1 :(得分:3)

不要抛出this:在捕获异常时,失败的对象不再存在。它已经被清理,析构函数调用它的成员和基类,并且它的内存由异常处理机制自动释放。试图再次删除它是一个错误。

只需抛出一个正常的异常类型(最好是std::exception的子类型),就像从任何其他函数那样抛出。

答案 2 :(得分:2)

~A()被调用两次的原因是因为在B()的正文中,A()已完全初始化,因此当发生异常时,~A()将自动调用虽然B()本身尚未完全初始化,但是~B()将不会被调用,如果构造函数抛出,您不需要也不应该删除指针,C ++将调用delete在那种情况下为你。请参阅LIVE DEMO

答案 3 :(得分:0)

1)B * b =新B;

完成A级建设

B类的构建不完整

2)抛出这个;

它将释放A类部分,所以~A()被调用,~B()不被调用,因为它的构造不完整

3)控制进入捕获(B * b)

删除b;

叫~B然后~A