Re: I don't have to tell you...
On Nov 28, 12:29 pm, Pavel
<pauldontspamt...@removeyourself.dontspam.yahoo> wrote:
BTW, I just found the reference to this article of Scott Meyers ibid in
Wikipedia:http://www.artima.com/cppsource/nevercall.html. I think
logically those who agree with this his opinion should agree to us
(Howard and myself) as well: what a point in having a "safety feature"
that is recommended to be used .. never?
I say "logically" because Scott himself would apparently disagree:
"... That's how every part of C++ will treat it, and the treatment makes
sense: the BuyTransaction-specific parts of the object haven't been
initialized yet, so it's safest to treat them as if they didn't exist".
I, on the other hand, cannot see a big difference between calling any
function within a constructor (where some parts of an object may not
have been initialized yet) and calling a virtual function ibid. I
believe that treating the derived-class object as "non-existing" before
entering its construction function is an arbitrary and not very useful
choice of the Standard.
Simple example.
//
#include <string>
struct F
{
virtual std::string const& name() const =0;
};
struct G : F
{
std::string name_;
virtual std::string const& name() const { return name_; }
};
//
Now, if I wrote that sample correctly, let's look at F and G. Suppose
F's constructor calls name() for debugging purposes. If it were to go
to the most derived but not yet constructed object G, then it would
return a reference to the not yet construct string sub-object, and any
attempt to use it would probably crash because it's not initialized:
the internal pointer of std::string would point to garbage and
dereferencing it would crash or be equivalently bad. Moreover, if
instead of string you had an object with virtual functions, then
calling anything on it would be bad because it's virtual table has not
yet been set up, so calling any virtual function on the sub-object
would horribly fail.
To repeat your statement:
I
believe that treating the derived-class object as "non-existing" before
entering its construction function is an arbitrary and not very useful
choice of the Standard.
Generally speaking, calling any sort of member function on any
nontrivial class which has not been initialized will dereference an
uninitialized pointer or do some equally bad thing because of the
uninitialized data. That's the reasoning behind this decision by the
standard to make virtual calls not go to member functions of classes
which have not yet been initialized or started initialization. I would
claim that it's quite a rare class which it makes sense to call member
functions on it without basic initialization of the data. (Well,
unless that member function is a setter, aka that member function is
initialization.)
It's a very useful guarantee to know that in a constructor that all of
your sub-objects (base class sub-objects and member sub-objects) have
been constructed. It's part of the whole thrust of C++ to not (easily)
allow access to unconstructed or destroyed objects. Ex: The "new"
operator returns a fully constructed object, you can't access an
uninitialized object through virtual pointers, etc. The whole language
and standard are built around this idea. I like it. It works for 99%
of cases. I don't recall yet seeing a case which I would actually want
to define a different construction order, nor call functions on an
object which has not been initialized.