简体   繁体   English

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

[英]Where am I supposed to catch the C++ exception thrown in the constructor?

Header file: 头文件:

#ifndef MUTEXCLASS
#define MUTEXCLASS

#include <pthread.h>

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

#endif // MUTEXCLASS

Source file: 源文件:

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

Where am I supposed to catch the exception thrown in the constructor? 我应该在哪里捕获构造函数中引发的异常?

An exception thrown in a constructor can be handled 可以处理构造函数中引发的异常

  • by the code explicitly creating the object ( try { MutexClass m; ... } catch(const std::logic_error& e) { ... } ) 通过显式创建对象的代码( try { MutexClass m; ... } catch(const std::logic_error& e) { ... }
  • by code creating an object that contains as member a MutexClass instance (including as base sub-object... ie by code that creates an object derived from MutexClass ) 通过代码创建一个包含MutexClass实例作为成员的对象(包括作为基本子对象...,即通过创建从MutexClass派生的对象的代码)
  • by code calling code doing the creation as exceptions will un-wind the stack until some code handles them 通过代码调用创建异常的代码将展开堆栈,直到某些代码处理它们为止

Note that for exceptions thrown in constructor of objects that are members of bigger objects (either for an has-a or a is-a relationship) there is a tricky part. 请注意,对于较大对象的对象的构造函数中抛出的异常(对于has-ais-a关系),有一个棘手的部分。 The destructor of the bigger object will not be called if the costruction of a member throws an exception... only the already constructed members will be destroyed before propagating the exception. 如果成员的构造引发异常,则不会调用较大对象的析构函数...在传播异常之前,只有已构造的成员将被销毁。 For example a class like: 例如一个类似的类:

struct Foo {
    MyData * data;
    MutexClass m;
    MyData() : data(new int[1000]) { }
    ~MyData() { delete[] data; } // NOT called if m constructor throws
};

will leak memory if MutexClass constructor throws an exception. 如果MutexClass构造函数抛出异常,将泄漏内存。

Also before writing an exception handler however ask yourself if catching the exception is the right thing to do (ie if you know what to do when that condition occurs). 同样在编写异常处理程序之前,请问自己是否捕获异常是正确的事情(即,如果您知道在发生这种情况时该怎么办)。 Catching an exception and "hiding" it because you don't know what to do in that case is the worst possible choice. 捕获异常并“隐藏”它是因为最糟糕的选择,因为在这种情况下您不知道该怎么办。

In the specific case if you cannot lock a freshly created mutex can you expect the system to be still in good enough shape that keeping it running is a good idea? 在特定情况下,如果您无法锁定新创建的互斥锁,您是否可以期望系统仍然处于良好状态,以使其保持运行状态是一个好主意?

As with any exception, anywhere up the stack where you can handle the exception. 与任何异常一样,您可以在堆栈中的任何地方处理异常。 This is no way different from handling exceptions thrown in functions. 这与处理函数中引发的异常没有什么不同。

At the point of construction 在施工时

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

or if you have a pointer 或者如果您有一个指针

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

If you were able work with a pointer , passed to a function , surround the function. 如果您可以使用传递给函数的指针,请将该函数包围起来。

Eg 例如

void funfun ( MutexClass * ); 无效funfun(MutexClass *);

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

If you are going to construct the object in an initializer list: 如果要在初始化列表中构造对象:

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

But now you have to handle the failure of the constructor of A as well. 但是现在您还必须处理A构造函数的失败。

Furthermore you should watch out for implicit conversions and copies, and you class is sadly copiable. 此外,您应该注意隐式转换和副本,而您的班级可悲地可复制。

void funfun(MutexClass m );   

pthread_mutex & m;
try
{
  void funfun(m);
} catch( std::logic_error const & e )
{
}

Read before throwing from a constructor. 从构造函数抛出之前先阅读

Also don't forget that such constructors are not good as static members. 也不要忘记,此类构造函数不适合用作静态成员。 So this type of class may break your program 所以这类课程可能会破坏您的程序

class maybreak 
{
private:

static MutexClass mc;

// ....

};

unless a wrapper function method is defined to put the construction of the static after your program actually starts ( COFU ). 除非定义了包装函数方法,以在程序实际启动之后放置静态构造( COFU )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM