我应该在哪里捕获构造函数中抛出的C ++异常?

时间:2015-12-25 08:48:53

标签: c++ exception

标题文件:

#ifndef MUTEXCLASS
#define MUTEXCLASS

#include <pthread.h>

class MutexClass
{
private:
    pthread_mutex_t & _mutexVariable;
public:
    MutexClass (pthread_mutex_t &);
    ~MutexClass ();
};

#endif // MUTEXCLASS

源文件:

#include "mutexClass.h"
#include <stdexcept>

MutexClass::MutexClass (pthread_mutex_t & arg) : _mutexVariable (arg)
{
    _mutexVariable  = PTHREAD_MUTEX_INITIALIZER;
    int returnValue = pthread_mutex_lock (&_mutexVariable);
    if (returnValue > 0)
    {
        throw std::logic_error ("Mutex couldn't be locked!");
    }
}

MutexClass::~MutexClass()
{
    pthread_mutex_unlock (&_mutexVariable);
}

我应该在哪里捕获构造函数中抛出的异常?

3 个答案:

答案 0 :(得分:5)

可以处理构造函数中抛出的异常

  • 通过明确创建对象(try { MutexClass m; ... } catch(const std::logic_error& e) { ... }
  • 的代码
  • 通过代码创建一个对象,该对象包含MutexClass实例的成员(包括作为基础子对象...即通过创建从MutexClass派生的对象的代码)
  • 通过代码调用代码执行创建异常将取消堆栈,直到某些代码处理它们

请注意,对于作为较大对象(has-ais-a关系)成员的对象的构造函数抛出的异常,有一个棘手的部分。如果成员的构造引发异常,那么较大对象的析构函数将被调用...在传播异常之前,只有已经构造的成员才会被销毁。例如,一个类:

struct Foo {
    MyData * data;
    MutexClass m;
    MyData() : data(new int[1000]) { }
    ~MyData() { delete[] data; } // NOT called if m constructor throws
};
如果MutexClass构造函数抛出异常,

将泄漏内存。

在编写异常处理程序之前,请问自己是否正确捕获异常(即如果您知道在发生该情况时该怎么做)。捕捉异常并“隐藏”它是因为你不知道在这种情况下该做什么是最糟糕的选择。

在特定情况下,如果您无法锁定新创建的互斥锁,您是否可以期望系统仍然保持良好状态以保持其运行是一个好主意?

答案 1 :(得分:2)

与任何异常一样,堆栈中的任何位置都可以处理异常。这与处理函数中抛出的异常没有什么不同。

答案 2 :(得分:-2)

在施工点

try {
  MutexClass m(arg);
}catch( std::logic_error const & e)
{
}

或者如果你有一个指针

try {
  MutexClass * m = new MutexClass(arg);
}catch( std::logic_error const & e)
{
}

如果您能够使用指针传递给函数,请将函数包围起来。

E.g。

void funfun(MutexClass *);

try {
  funfun(new MutexClass(arg));
}catch( std::logic_error const & e)
{
}

如果要在初始化列表中构造对象:

class A
{
MutexClass mc;
A(pthread_mutex_t & m) try : mc(m)
{
} catch ( std::logic_error const & e )
{
// do something here to handle the failure 
// of mc(m) and the now the failure of A 
// must be handled in the construction point of A 
}
};

但是现在你必须处理A的构造函数的失败。

此外,你应该注意隐含的转换和副本,而且你的课程很可遗传。

void funfun(MutexClass m );   

pthread_mutex & m;
try
{
  void funfun(m);
} catch( std::logic_error const & e )
{
}
来自构造函数的

Read before throwing

另外不要忘记这样的构造函数不如静态成员。 所以这种类可能会破坏你的程序

class maybreak 
{
private:

static MutexClass mc;

// ....

};

除非定义了wrapper函数方法,以便在程序实际启动后构建静态(COFU)。