Or, rephrased: RAII is incredibly attractive, especially when exceptions are being used.
The thing that is hard to replicate in C is destructors. Automatic deinitialization when leaving scope in very convenient. It allows you to have multiple exists from the scope without preceding each of them with prologue of dinit_*() calls or creating single exit point and jumping to it.
Coupling allocation with initialization is trivial to do without C++ constructors (which I find to be very poorly designed).
As for "why not stick with C"--all of the other reasons still hold true, from templates on down. The simple existence of dtors with viable scope guards that are guaranteed to fire when exiting scope is reason enough for me to never write C and to look with a default skepticism on any codebase that thinks its developers are perfect enough not to need them.
class Foo {
public:
static std::optional<Foo> create();
private:
Foo();
};This now means that you can't use any constructors, so how do you have Containers of foo?
So you then have things like:
class Foo
{
public:
static Foo* create();
...
};
...
Foo* foo = Foo::create()
if ( foo != nullptr ) ...
> so how do you have Containers of foo?std::vector<Foo*>
Not saying either of those are better than the alternative (I prefer using exceptions and RAII), just pointing out what I've seen in real world projects.
class Foo
{
public:
Foo();
bool initialize(); // returns success
...
};
...
Foo foo;
if ( !foo->initialize() ) { // handle error }
This also means you can break up your initialization so that you drive the risky pieces from outside the object, rather than monolithically from within.This has a further benefit for testing, since you can use your major objects without fully initializing the entire world that they depend on.
It's also a technique that is widely used. See for example the cocos2d-x game library.
The benefit of such a technique is that you can then make the constructor private, making it impossible to create an object and not also call the initialize() method.
Using a separate initialize member function means that you may have objects in a zombie state laying around after a failed construction which lead to all kind of initialization order issues (you might get a pointer to the object, but is it initialized?). Also you need to remember to check the return type, which also need to be meaningful (does it return false on failure? or it returns 0 on success?).
Two phase initialization is a known antipattern which is, unfortunately, widely used and lead to all kind of pains.
Friends do not let friends use 2PI.
edit: sorry, I misread your comment, you were referring to the static function returning a pointer, which as you note is almost the same as the optional version. It forces heap allocation though, which is bad.
class Foo
{
public:
static Foo* create()
{
Foo* result = new Foo(); //exceptions disabled so new can return nullptr
if ( result )
{
//configure result here
}
return result;
}
private:
Foo() {}
};
...
Foo* badFoo = new Foo(); // compiler error because Foo() is private
Foo* foo = Foo::create(); //all good, no 2PI and can't forget to call initialize code
if ( foo ) //check for non-null, note, if using an optional you'd also need a similar check
{
...
}
Now the only way to create a Foo object is through the create() function and there is no separated initialize - it all happens in the same place.This pattern of using a static create method is explicitly designed to avoid 2PI and is very common, especially in codebases that disable exceptions.
Also note that I'm not personally advocating using it, just that it is commonly used to avoid 2PI.
You can have contiguous Foos, but not in a vector. You can either have another static function to return an array of Foos, or more commonly have some sort of pool allocator and have the create function allocate objects from the pool.
Anyway, yes, there are limitations for using this pattern, so like all things it's a matter of weighing up the tradeoffs.
It does, and it can be, but in situations where it matters, the static create function typically returns a value from a preallocated pool of memory, so objects are all contiguous and cache friendly.
There are definitely things to be aware of before adopting such a pattern, or when trying to optimize code that uses it.
The examples that come immediately to mind are the Publiser, Subscriber, and Timer classes that are part of the ROS C++ API: http://docs.ros.org/api/roscpp/html/classros_1_1Publisher.ht...
I agree that there are caveats with it, but I get nervous when people toss around a phrase like "known antipattern" with such confidence.
About the container issue: if you have objects that might fail during the creation it seems like a bad idea to allow things like:
std::vector<Foo> foos(10);
Having a separate initialization method which might fail - like proposed by others - is another option, but this means your objects need some kind of internal initialization state, and whenever you're handling such an object you never can be absolute sure that it's in a valid state.I'm quite a big fan of making invalid state not representable in an object and handling failure cases as early as possible.
What the create method returns depends heavily on your use case. If the returned objects can always be allocated on the heap, then a pointer or unique_ptr can be returned.