views:

138

answers:

6

I was looking at the Google C++ Style Guide and they have decided not to use exceptions in C++ code, relying on return values instead.

My question is: How do you handle failure in constructors in this case, since you cannot return a value in those.

Thanks!

+1  A: 

You could set a class/object field to check if you incurred in an error.

klez
If the object doesn't get constructed, how do you check it?
Joe
@Joe, set the flag at the beginning of the constructor and clear it at the end. Or vice versa.
Mark Ransom
+7  A: 

My first instinct would be to take the failure point out of the constructor, and create an initialisation method.

This way you can create your object without fear of failure, then call the init() function. That function can return something like an int for success/failure, for example -1 if the failure occurs.

Yes this is an extra step, but it does get you around not being able to fail a constructor

Dunderklumpen
See http://www2.research.att.com/~bs/3rd_safe0.html for an excellent and very detailed explanation of why not to implement an init() routine.
John
In general (I'm mostly a java coder), I do not like the possibility of exceptions occurring in a constructor anyway, and I tend to take this sort of approach.
Dunderklumpen
@Dunker: In C++? Don't program Java in C++, program C++ in C++.
GMan
Isn't this against RAII?
dreamlax
It's entirely against RAII. That's how Java programmers get confused; they don't have RAII to start with.
MSalters
It seems that this approach is against good C++ practice; however, given the constraint, I think it is the simplest way to go.
recipriversexclusion
+4  A: 

It's pretty ugly, but the way to do it is to reserve a "special state" of the object to mean "construction failed". Then you have to query that state. Ugh!

John
+2  A: 

They basically do nothing in their constructors.

Also from the Google C++ Style Guide: Doing Work in Constructors link ▶ In general, constructors should merely set member variables to their initial values. Any complex initialization should go in an explicit Init() method.

rhinoinrepose
You can try to allocate memory and fail.
recipriversexclusion
@recip: that would be complex initialization.
Potatoswatter
+2  A: 

You can do the following:

class X;
class Y;

class Foo
{
   public:
      //! This function validates the input, and returns an error status if
      //! the Foo can not be created. Otherwise we return a successful status
      //! and output points to a newly constructed Foo. The Foo constructor 
      //! is only called once the inputs are validated.
      //! No exceptions are thrown.
      static Status buildInstance(X const& x, Y const& y, std::auto_ptr<Foo>& output);

   private:
      Foo(X const& x, Y const& y);
};

I have used this pattern frequently in the past (because I had to), but that said, I much prefer my constructors to throw exceptions. The above is inelegant at best and quite cumbersome at worst.

Craig W. Wright
+1  A: 

I'm new to C++ so my opinion is not worth all that much; but I've encountered at least a couple of different approaches.

In one library that I was using recently, every constructor has an int& argument that returns the status of construction; the documentation for this library states that it will invoke undefined behaviour if the construction result is invalid. This approach makes it the caller's responsibility to ensure not to use the invalid class.

TheClass::TheClass(int &result)
{
    result = -1; // or some error value
    // do lots of initialisation
    result = 0; // success
}

Another one that I saw had an is_valid() method. If the construction failed, a boolean member variable was set to false and was returned from this is_valid() method (this method also checked a couple of other things as well). I managed to see the source for this and found each member function starting out with an if(is_valid()) statement. I can't say I'm a fan of this approach.

TheClass::TheClass() : m_valid(false)
{
    // do the initialisation
    if (everything_ok)
        m_valid = true;
}

void TheClass::method()
{
    if (!is_valid()) return;
    // do some work
}

I've read recently however that exceptions aren't as slow and kludgy as they used to be, and it is possible to implement them elegantly. Google may prohibit them for whatever reason, but they're still part of the C++ language. You might as well work with the tools you're given than to build a house with just a screwdriver.

dreamlax