How to deal with failed constructor when throwing exceptions is not allowed
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 开发者_JAVA技巧in constructors in this case, since you cannot return a value in those.
Thanks!
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
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!
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.
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.
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.
You could set a class/object field to check if you incurred in an error.
精彩评论