views:

1331

answers:

6

Im 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, form 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 i unusable so throwing an exception ensures that the mutex won't be created.

Should I rather create a init function on the Mutex class and call pthread mutex_init there? This way i don't have to use exceptions for such a low level object.

+24  A: 

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.

Naveen
In most situations. Don;t forget things like std::fstream. On failure it still creates an object, but because we are always testing the state of the object normally it works well. So an object that has a natural state that is tested under normal usage may not need to throw.
Martin York
+1  A: 

Although I have not worked C++ at a professional level, in my opinion, it is OK to throw exceptions from the constructors. I do that(if needed) in .Net. Check out this and this link. It might be of your interest.

danish
+12  A: 

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.

anon
I'd second Neil's point about the exception heirarchy - a single MutexError is likely to be a better choice unless you specifically want to handle a lock error differently. If you have too many exception types, catching them all can become tiresome and error prone.
markh44
I agree that one type of mutex exception is enough. And this will also make error handling more intuitive.
lkristjansen
+2  A: 

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.

e.g.

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
    { ... }
Ferruccio
It should be noted that exceptions raised from the construction of a sub object can't be suppressed: http://www.gotw.ca/gotw/066.htm
Éric Malenfant
I think 'try' goes before the colon and the initializer list in the second bit of code
Steve Jessop
@onebyone.livejournal.com: nice catch (ha ha)
Ferruccio
+1  A: 

It is OK to throw from your constructor, but you should make sure that your object is constructed after main has started and before it finishes:

class A
{
public:
  A () {
    throw int ();
  }
};

A a;     // Implementation defined behaviour if exception is thrown (15.3/13)

int main ()
{
  try
  {
    // Exception for 'a' not caught here.
  }
  catch (int)
  {
  }
}
Richard Corden
A: 

The only time you would NOT throw exceptions from constructors is if your project has a rule against using exceptions (for instance, Google doesn't like exceptions). In that case, you wouldn't want to use exceptions in your constructor any more than anywhere else, and you'd have to have an init method of some sort instead.

Michael Kohne
anon
Interesting discussion. My personal opinion is that you should use exceptions only when you actually design the program's error handling structure to take advantage of them. If you try to do error handling after writing the code, or try to shoehorn exceptions into programs that were not written for them, it's just going to lead to either try/catch EVERYWHERE (eliminating the advantages of exceptions) or to programs crashing out at the least little error. I deal with both every day and I don't like it.
Michael Kohne