Also to support the idea of seamless type conversion, I guess. When it
looks like you're calling T(x), it makes a kind of sense to have the
invoked function named T. Except that it's really T::T, so the illusion
breaks down very very rapidly, and just incurs a host of problems...
Especially as T(x) doesn't necessarily call T::T---it might also
call TypeOfX:
perator T.
I think the real question is simply: if it's going to be defined
like a function, it needs some sort of name. And at the time
constructors were introduced (very, very early in the language),
there was still some sort of resistence to adding
keywords---arguably, a special keyword name, like "constructor"
or "destructor" would have been more appropriate.
But I don't think it really matters that much. The current
situatation doesn't cause any real problems either.
Well. In early (pre-standard) C++ you could assign to 'this'. Not
'*this', but 'this'.
Been there, done that. Assignment to this was only allowed in
the constructor, only before you accessed any members, and had
special semantics (basically, the equivalent of defining a
member operator new() today).
So one might say that what a constructor returned then,
technically, was the address of the constructed object. But
that was under the hood.
I suspect that there are still some implementations that do this
under the hood. The orginal CFront passed the address of a
object to be constructed to the constructor, or a null pointer
if the memory was to be allocated dynamically. The code
generated for the constructor tested for null, and called new,
And the constructor did return the pointer, which was what was
assigned in something like "p = new ...".
One might also say that an expression like 'T(x)' calls the
constructor, and returns an object. From a users point of view,
that's fairly close to the way a lot of people think of it.
What's interesting here is that the C++ constructor mechanism really
requires exceptions of some kind. Because objects need not be
dynamically allocated, so failure can't be signalled via 'this'. And
that this breaks down in environments that don't support exceptions.
It would need exceptions even if it returned the pointer,
because there would be no way of accessing it in the declaration
of a local variable. (But that's really subsumed in what you
said.) More generally, constructors guarantee the invariants of
an object---if a constructor can't do that, you need some sort
of mechanism which guarantees that the object doesn't exist.
Given local and static variables, it's hard to imagine what that
mechanism could be, if it wasn't exceptions.
And one sort-of-obvious alternative design for such environments could
be where you can declare storage for an object of a type T without the
ability to use that storage directly, but only through a typed pointer
returned by a constructor. And... Hey, C++ supports that already! <g>
At least, sort of. A little helper machinery would help much. Using
temporaries would be a problem, I think (interesting to think of
possible solutions for supporting that...).
One could imagine all sorts of things. However...
Is the current situation really broken? Does it need fixing?
(IMHO, the only really viable alternative would be to require
all objects to be allocated on the stack, a la Java. Which has
other disadvantages.)