Throwing exceptions from constructors

I'm having a debate with a co-worker about throwing exceptions from constructors, and thought I would like some feedback.

Is it ok to throw exceptions from constructors, from a design point of view?

Lets say I'm wrapping a posix mutex in a class, it would look something like this:

class Mutex {
public:
  Mutex() {
    if (pthread_mutex_init(&mutex_, 0) != 0) {
      throw MutexInitException();
    }
  }

  ~Mutex() {
    pthread_mutex_destroy(&mutex_);
  }

  void lock() {
    if (pthread_mutex_lock(&mutex_) != 0) {
      throw MutexLockException();
    }
  }

  void unlock() {
    if (pthread_mutex_unlock(&mutex_) != 0) {
      throw MutexUnlockException();
    }
  }

private:
  pthread_mutex_t mutex_;
};

My question is, is this the standard way to do it? Because if the pthread mutex_init call fails the mutex object is unusable so throwing an exception ensures that the mutex won't be created.

Should I rather create a member function init for the Mutex class and call pthread mutex_init within which would return a bool based on pthread mutex_init's return? This way I don't have to use exceptions for such a low level object.


Yes, throwing an exception from the failed constructor is the standard way of doing this. Read this FAQ about Handling a constructor that fails for more information. Having a init() method will also work, but everybody who creates the object of mutex has to remember that init() has to be called. I feel it goes against the RAII principle.


If you do throw an exception from a constructor, keep in mind that you need to use the function try/catch syntax if you need to catch that exception in a constructor initializer list.

eg

func::func() : foo()
{
    try {...}
    catch (...) // will NOT catch exceptions thrown from foo constructor
    { ... }
}

vs.

func::func()
    try : foo() {...}
    catch (...) // will catch exceptions thrown from foo constructor
    { ... }

Throwing an exception is the best way of dealing with constructor failure. You should particularly avoid half-constructing an object and then relying on users of your class to detect construction failure by testing flag variables of some sort.

On a related point, the fact that you have several different exception types for dealing with mutex errors worries me slightly. Inheritance is a great tool, but it can be over-used. In this case I would probably prefer a single MutexError exception, possibly containing an informative error message.

链接地址: http://www.djcxy.com/p/86826.html

上一篇: 如何调试赢32进程来查找内存访问冲突?

下一篇: 抛出构造函数的异常