Full constructor, unless for some reason you're trying to avoid using exceptions in your code base.
I'm not going to go into the arguments for and against banning all exceptions, but for instance in C++ if you're not using nothrow new everywhere, then you aren't avoiding all exceptions, so the special case doesn't apply.
Getting back into more language-agnostic territory, you might argue that "exceptions are for exceptional cases only", but also that "this constructor failing is not exceptional". I'm not going to go into the arguments for or against that, either, but it leaves you with two options:
1) Set a "failure" flag on the object if construction fails, and callers have to check it (either explicitly, or it's checked in other functions which behave differently according to whether it's set). C++ file streams do this with the constructor that takes a filename. It's a nuisance for the caller, but less of a nuisance than two-stage construction.
2) Have a helper object to perform the operations which can fail but which should not be exceptions, and make callers use this. That is, replace:
MyObj(a,b,c); // might throw
with
MyArgs args(a,b,c);
// optionally, if caller doesn't want an exception
if (!args.ok()) handle_the_error();
MyObj(args);
Then in the constructor that takes a MyArgs, MyObj can also call args.ok()
, and throw an exception if they aren't. One class could offer both constructors (or factory methods if your language doesn't allow multiple constructors), and let the caller decide.
Fundamentally, if you want to avoid an exception, then the caller is going to have to manually check for success somewhere. Personally I think that if the reason for failure amounts to bad arguments, then it's better to check beforehand. Obviously file streams can't do that, because whether the argument is "bad" or not can change if the filesystem is modified between the check and the constructor. So you have no choice but to check afterwards. This is still better than two-stage construction.
If you absolutely must have two-stage construction of the object itself, then I think it's best to hide that in a factory method. Assuming your language allows some kind of "null" to indicate errors, that is.