March 06, 2002
"Immanuel Scholz" <digitals-mars@kutzsche.net> wrote in message news:a65lid$17pl$1@digitaldaemon.com...

> Most functions that depend on initialised members
> have to depend on them and cannot simple "not using" them.
> You may add a check before the first use of them in each of
> your function, but I think this is buggy (because easy to forget)
> and not good detectable at debug-time for all cases.

Just don't call such functions from the point where
members aren't yet properly initialized. Invariants
will help to trap such cases and fix them, so you can
be sure that in the release build you'll never get
such a mistake - so checks aren't needed!


> This means, "class invariants" degrees to helper-functions that are called
> before each member function is called. This is not their normal usage.
> I would not recommend this.

And what are invariants if not "helper functions"? They help you to ensure validity of object's state, don't they?


> No source, or not the posibility to compile the source. Simple, it is not your code, that calls the function, its a code you are forced to use.

I understand now. I thought you meant to forbid calling the constructor of the base class explicitly. =)

> No, sorry. You cannot fool the compiler to resolve a virtual function, if
> the vpt of the class is not already build. All calls to virtual functions
> will
> be static linked until the constructor ends (without an exception, of
> course). That's the way C++ goes, and it will not run into this problem.

But what if compiler calls another function which calls a virtual function? I guess C++ doesn't actually do static calls, it just uses the vtable built to the needed stage, since child constructors haven't yet been executed, vtable contains pointers to methods of this class or its ancestors only.

> Yes, I think so too. It is a good feature to be able to call virtual functions, and it is some kind of suprising, if you first time realize,
that
> there is a static linkage with constructors.
>
> But I think, the problem I stated should NOT BE IGNORED!
> Maybe a solution could be, that all function called from within
> the constructor (and all functions they call and so on) are
> somewhat marked, and checked, whether they use members of the
> class. If so, the compiler shoud give a warning or something like that.
>
> So you can do this without any problem:
>
> class B {
>   this() { printf( "I am a %s.",myself(); }
>   char[] myself() {return "Base";}
> }
>
> class D {
>   char[] myself() {
>     return "Derrived";  // give no warning, since no
>           // member-variable is touched.
>   }
> }
>
> This is a common and good usage for the call to virtual functions
> from the constructor (and currently not possible in C++). Instead,
> this would produce at least a warning (if not an error at all?)
>
> class D {
>   int i = 0;
>
>   char[] myself() {
>     // WARNING! "use of 'i' as a rvalue. Constructor may not be completed.
>     if (i == 1)
>       /* do something */
>    return "Derrived";  // give no warning, since no
>           // member-variable is touched.
>   }
> }
>
> How about this? I don't know if it is possible (I think it is not, because
> I do not know how the compiler could resolve the correct
> function that is called at compile-time).

Yes, exactly. Unless we have AI built into the compiler, I guess these are just dreams. So the question is, should this feature be forbidden at all (because it might be used improperly), or should it be left (because it is a very powerful tool when used properly). I vote for the second.




March 06, 2002
"Pavel Minayev" <evilone@omen.ru> schrieb im Newsbeitrag news:a65n8o$18jp$1@digitaldaemon.com...
> "Immanuel Scholz" <digitals-mars@kutzsche.net> wrote in message news:a65kdh$17b2$1@digitaldaemon.com...
>
> > Hmm... Yes.
> >
> > Why doesn't D support const functions and classes? I thought they cast away more problems than they do? (And they give the compiler the chance to optimization).
> >
> > I like const functions...
>
> Const functions operate only on const objects. And you cannot have const objects in D, since no objects are on stack, and all constants must be literals:
>
>     Object foo;                     // actually a pointer to foo
>     const Object bar;               // impossible: no initializer!
>     const Object baz = new Object;  // wrong: constant expression required

Hm... I do not understand, why this should be a problem.
With my conses of const, you can only initialize a const object, but never
assign to it (or call non-const functions) and of course, you can only
initialize any object-instance once.

Whether the object is on the heap or stack or static or not doesnt matter.

Object foo;    // agreed, its a pointer. (a non-const one..)
const Object bar;  // bar is just initialized and then, compiler forbids to
// call non-const functions (e.g. operator= is non-const)
const Object baz = new Object;  // the object baz is only initialized once,
// with the copy-constructor. There is no assignment or anything like
// two initialisations. Also no temporary object is created.

So wheres the problem with const and no stack-variables?
(Hm, maybe we get this part of the posting to a new thread? ;-)


> > Oh dear, you are right. So this makes no sense too.. I become thinking that static linkage within constructors is the best solution (The
solution
>
> Is it?
>
>     class Foo
>     {
>         int n;
>         this() { init(); n = 666; }        // calls init() statically
>         void init() { foo(); }    // calls foo() dynamically via vtable
>         void foo() { ... }
>     }
>
>     class Bar: Foo
>     {
>         void foo() { printf("%d", n); }
>     }
>
> Piece of cake! =)

No, piece of sh**t, because the vtable is initialized, when the constructor
finished successful, so all calls, even the foo() will be static linked (no
vpt -
no dynamic linkage - no surprises with functions called before constructor
finished)



March 06, 2002
(Not in reply to any particular person - I'm just clarifying this issue in
my mind)

So - the way an object in D is built is:

1. Allocate the needed memory.

2. Copy a compiler-built static image, which includes the final vtbl pointer, into the new memory.

3. Call the constructor of the actual "outermost" instance type.

4. The instance's constructor calls superclass constructors at it's convenience.

This is philosophically different from C++, which believes it's wrong to touch the methods of a descendant object until it's superclass is fully constructed.  C++ calls constructors in the opposite order, innermost-first.

(In C++, in the presence of virtual overrides, there would have been potential for a base  constructor to call a descendant's method, except that C++ rules that descendant methods can NOT be called by a parent's constructor.  So it's as if the object being constructed gradually evolves from the innermost base class, into the actual instance type, by updating the vtbl pointer at each level of construction.)

So the order of construction for class C derived from B derived from A is,
C.this() calls B.this(), which calls A.this().  And C.this() can touch and
invoke any of C's methods or variables, before calling B.this(), effectively
*without* having a "valid" base class.

And, now I can see it: C.this() can also touch any of A's methods and
variables before A.this() is called, effectively before A is a valid object.
Hmmm.

Now, Walter says (unless I'm mistaken) that this is okay because there are never any uninitialized areas of storage.  All of A's and B's and C's static constructors "happen" before any .this() is called.

So, if it's important, I see how this you can use this as a safety net.

class A
{
   private int A_constructed = 0;
   this()
   {
      // ...
      A_constructed = 1;
   }
}

Any of A's methods that are called before A.this() can see A_constructed ==
0 (if they look).

But they *do* have to look.  And in C++ they wouldn't have to.  So in this respect, D is not as safe as C++.

Now, as a long-time C programmer, I'm willing to sacrifice some safety for power.  But frankly, I'm not seeing how this adds power.  If anyone can come up with a concrete example that shows the power of calling base class methods before calling the base class constructor, I'd appreciate it.

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@comcast.net  (personal)



March 06, 2002
Dear Immanuel,

You were right that I missed your point, I see it
now...  :)
I agree that calling a virtual function from within a
constructor might cause trouble, however there does
not exist an effective solution to that problem.
You state that being able to call a virtual function from
a constructor is bad, because now you can't trust your
object to be initialized in any function when you inherit
from a base class that someone else programmed.
Consider this however:
I state that you can't trust your object to be initialized
in any function when you inherit from a base class
someone else programmed, period.
How are you ever going to be sure that the author of
the base class did his work properly and initialized all the
member variables in the constructor at all?
Virtual function calls or not, the fact of the matter is that
you can't be sure.

Consider this C++ code:

class Foo
{
   CImportantClass *pVeryImportant;

   Foo ()
   {
      // Oops, forgot to initialize my all important pointer.
      // it is not even NULL, it is just garbage!
   }
};

class Bar: public Foo
{
   void MyFunction()
   {
      pVeryImportant->IAmDead();       // Crash and burn...
   }

   void AnotherTry()
   {
      if (pVeryImportant != NULL)     // Won't help, because
      {                                                // the pointer is
garbage
         pVeryImportant->IAmDead();       // And crash again...
      }
   }
};

Now how is any construct going to protect you against
this? You see, D already greatly improves on the situation.
If you use code that is very badly programmed, you will
be in trouble anyhow. The point of D is to make it easy to
write good code, not impossible to write bad code.

Your point that it might cause trouble remains valid though.
Walter does not like warnings, otherwise one might be
issued when you override a function from a base class that
is called from it's constructor, and one might be issued when
you call a function from a constructor without prepending it's
class name, meaning you would write DoSomething();
instead of MyClass.DoSomething(). Otherwise I don't see
a good solution, without seriously hampering an otherwise
very powerful language feature.


--
Stijn
OddesE_XYZ@hotmail.com
http://OddesE.cjb.net
__________________________________________
Remove _XYZ from my address when replying by mail



March 06, 2002
"Pavel Minayev" <evilone@omen.ru> schrieb im Newsbeitrag news:a65n91$18ju$1@digitaldaemon.com...
> "Immanuel Scholz" <digitals-mars@kutzsche.net> wrote in message news:a65lid$17pl$1@digitaldaemon.com...
>
> > Most functions that depend on initialised members
> > have to depend on them and cannot simple "not using" them.
> > You may add a check before the first use of them in each of
> > your function, but I think this is buggy (because easy to forget)
> > and not good detectable at debug-time for all cases.
>
> Just don't call such functions from the point where
> members aren't yet properly initialized. Invariants
> will help to trap such cases and fix them, so you can
> be sure that in the release build you'll never get
> such a mistake - so checks aren't needed!

GRRR! Am I talking to a wall? :-|

You can NOT (!) always remove the call to the function, because it may be
essential to the library or you simple CANNOT change the source code,
that calls the function.
In C++, your argument is correct, since only your own constructor of
your own class you are currently writing will call anything, so the only
place to look after, is your own constructor.

But in D, the call can come from a base-class constructor, or a function a base-class constructor calls.

Another example (a more real one:)

------ this is a library you don't own the sources -------
class Window
{
  this() { if (cmdline == "-with-window") CreateWindow(); }

  void CreateWindow() = 0;  // user have to implement how to do this
...
}

----- this is your code. Here you may change anything ------
class MyWindow
{
  FileWrapperClass* file = null;
  this () {...; super(); ...; file = new FileWrapperClass; }

  CreateWindow()
  {
    file.load_window_resources();    // <-- null-pointer-access !
  }
}


The problem here is, that you even might not know, that there are a switch
"-with-windows" in Window - class (or the switch is added later one, when
MyWindow was already compiled and shipped 1000 yards away),
so you do really not expect, that MyWindow.CreateWindow is called,
before the constructor finished.
And so you thought, that "file" must be in a correct state - but it isn't.

You cannot change the constructor of Window not to call CreateWindow
(you may even want it not to change). So all you can do is building a check
to CreateWindow() whether the constructor finished or not.
And this is buggy, because you normally would not spot the bug, until it is
too late (because you do not know about "-with-windows" or it wasn't
there as you code MyWindow)

class invariants help no good if stripped out in release (and thats what they are for, they do not ensure runtime-effects, only compile-bugs!)


> > This means, "class invariants" degrees to helper-functions that are
called
> > before each member function is called. This is not their normal usage. I would not recommend this.
>
> And what are invariants if not "helper functions"? They help you to ensure validity of object's state, don't they?

Maybe they can help to spot some of the problems, but anyway, I think
they this is no really solution.
If you spot such a case (which mean, you are lucky), you have to
add a check inside the functions body, since you cannot alter the base-class
and CreateWindow might be called if constructor is finished...


> > No source, or not the posibility to compile the source. Simple, it is not your code, that calls the function, its a code you are forced to
use.
>
> I understand now. I thought you meant to forbid calling the constructor of the base class explicitly. =)

If have my problems with this too, but this is another story.

As example some of my thoughts about explicit calling:
- Protect the compiler the access to the base classes members and
member-variables, before the super-constructor is called at least once?
- If you do not call the base class constructor, it is automatically called?
- If yes, before the current constructors code?

If all questions resolve to "yes", I am satisfied, elsewhere I may begin a new thread with these topics?


> > No, sorry. You cannot fool the compiler to resolve a virtual function,
if
> > the vpt of the class is not already build. All calls to virtual
functions
> > will
> > be static linked until the constructor ends (without an exception, of
> > course). That's the way C++ goes, and it will not run into this problem.
>
> But what if compiler calls another function which calls a virtual
function?
> I guess C++ doesn't actually do static calls, it just uses the vtable built to the needed stage, since child constructors haven't yet been executed, vtable contains pointers to methods of this class or its ancestors only.

IMHO, this is the way it goes. During constructor phase, the object simple IS a type of the current class. You can easily check this by:

-----
#include <iostream>
#include <typeinfo>
using namespace std;

class foo {
public: foo()  { cout << typeid(this).name() << endl; }
};

class bar : public foo {
public: bar() { cout << typeid(this).name() << endl; }
};

void main()
{ bar b; }
-----

This means, childs functions are protected from access through the base class constructor, and the base class functions are protected, since you cannot do any statement before calling the base-constructor.

Ok, there is a way, but this is terrible and a bug in C++-design:

class foo {
  public: foo(int);
  int some_function();
}
class bar : public foo {
  bar() : foo(some_function());  // some_function is called before the
          // base-class constructor!!!
}

But this requires explicit badness by the programmer.


> > Yes, I think so too. It is a good feature to be able to call virtual functions, and it is some kind of suprising, if you first time realize,
> that
> > there is a static linkage with constructors.
> >
> > But I think, the problem I stated should NOT BE IGNORED!
> > Maybe a solution could be, that all function called from within
> > the constructor (and all functions they call and so on) are
> > somewhat marked, and checked, whether they use members of the
> > class. If so, the compiler shoud give a warning or something like that.
> >
> > So you can do this without any problem:
> >
> > class B {
> >   this() { printf( "I am a %s.",myself(); }
> >   char[] myself() {return "Base";}
> > }
> >
> > class D {
> >   char[] myself() {
> >     return "Derrived";  // give no warning, since no
> >           // member-variable is touched.
> >   }
> > }
> >
> > This is a common and good usage for the call to virtual functions
> > from the constructor (and currently not possible in C++). Instead,
> > this would produce at least a warning (if not an error at all?)
> >
> > class D {
> >   int i = 0;
> >
> >   char[] myself() {
> >     // WARNING! "use of 'i' as a rvalue. Constructor may not be
completed.
> >     if (i == 1)
> >       /* do something */
> >    return "Derrived";  // give no warning, since no
> >           // member-variable is touched.
> >   }
> > }
> >
> > How about this? I don't know if it is possible (I think it is not,
because
> > I do not know how the compiler could resolve the correct function that is called at compile-time).
>
> Yes, exactly. Unless we have AI built into the compiler, I guess these are just dreams. So the question is, should this feature be forbidden at all (because it might be used improperly), or should it be left (because it is a very powerful tool when used properly). I vote for the second.

I do not live good with this...
Maybe because I always think, that the constructor have to be
something special..

There is nothing before the constructor, and if the constructor passed by, I got a valid object in a valid state.

This is the dreaming of the right way, object-design should be, and I think it is too much violated with rules like the one above.

So people start to write objects, where the constructor does
simple nothing or nearly nothing (since someone, IMO stupid
person, said "never raise an exception within a constructor").
And they wrote functions like init() or Create() to take the
place of a constructor... like in MFC which stinks because
those. (Ok, to be honor, MFC does something about the
Create() even because the fact, that no virtual function is
resolved ;-) but there are other ways to do it, like other
libraries does.)

Such a design - I mean to violate the rule, that "no member function is called implizit before the constructor." - does not invite people to write better OO-Code.

(Thats just my opinion, I am open to flames and any
other way of discussion ;-)

Maybe there are other solutions to this?
btw: how is it solved in Java?

Imi.



March 06, 2002
Richard Krehbiel wrote:

> Now, as a long-time C programmer, I'm willing to sacrifice some safety for power.  But frankly, I'm not seeing how this adds power.  If anyone can come up with a concrete example that shows the power of calling base class methods before calling the base class constructor, I'd appreciate it.

I ran across this sort of situation in a library I was developing in C++:

class Worker {...};
class Thing
{
protected:
    Worker *myWorker;

public:
    Thing() { myWorker = new Worker };
}
class WorkerChild : public Worker {...};
class ThingChild : public Thing
{
   // how do I create a WorkerChild object and pass it to my
   // parent class?  I want to use WorkerChild as the worker
}



The problem I ran into was that when you implement the ThingChild constructor, you must pass values into the Thing constructor.  But you can't call 'new' in the defintion, since that will work in some compilers but break in others.  What I really want to do was to be able to call the Thing constructor from INSIDE the ThingChild constructor...then I can make runtime decisions about the parameters of the WorkerChild and create it dynamically.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]


March 06, 2002
"OddesE" <OddesE_XYZ@hotmail.com> schrieb im Newsbeitrag news:a65rs6$1ait$1@digitaldaemon.com...
> I state that you can't trust your object to be initialized
> in any function when you inherit from a base class
> someone else programmed, period.
> How are you ever going to be sure that the author of
> the base class did his work properly and initialized all the
> member variables in the constructor at all?
> Virtual function calls or not, the fact of the matter is that
> you can't be sure.

The construct of calling a virual function from a constructor may be a good idea! (This is the real problem, it IS still a powerful tool you can use for good as for bad ;-)

See the example with CreateWindow in my other post...


> Consider this C++ code:
>
> class Foo
> {
>    CImportantClass *pVeryImportant;
>
>    Foo ()
>    {
>       // Oops, forgot to initialize my all important pointer.
>       // it is not even NULL, it is just garbage!
>    }
> };

This is surely a mistake and should be blamed to the author of Foo! It is a real bug, not a class design, I think.


> Now how is any construct going to protect you against
> this? You see, D already greatly improves on the situation.

Yes, most because the member are preinitialized (so this gives at least the chance for a workaround ;-)


> If you use code that is very badly programmed, you will
> be in trouble anyhow. The point of D is to make it easy to
> write good code, not impossible to write bad code.

But I would add the statement "it should not be easy to get errors, that are hard to understand."


> Your point that it might cause trouble remains valid though. Walter does not like warnings, otherwise one might be

:-[ It seems, that Walter does like printf, or why there are a static printf - member in Object? :-(

Why does Walter do not like warnings?

> issued when you override a function from a base class that
> is called from it's constructor, and one might be issued when
> you call a function from a constructor without prepending it's
> class name, meaning you would write DoSomething();
> instead of MyClass.DoSomething(). Otherwise I don't see
> a good solution, without seriously hampering an otherwise
> very powerful language feature.

Hm, I am still in doubt if this is good... maybe these "already initialized" - checking can be automated by the compiler?

Imi


March 06, 2002
"Immanuel Scholz" <digital-mars@kutzsche.net> wrote in message news:a65pp1$19kf$1@digitaldaemon.com...

> Object foo;    // agreed, its a pointer. (a non-const one..)
> const Object bar;  // bar is just initialized and then, compiler forbids
to
> // call non-const functions (e.g. operator= is non-const)
> const Object baz = new Object;  // the object baz is only initialized
once,
> // with the copy-constructor. There is no assignment or anything like // two initialisations. Also no temporary object is created.

In D, constants are always compile-time. That's one of its major
differences from C++. As the result, constants turn out to
be literals, or expressions involving literals and/or other
constants. No memory is allocated for consts.


> No, piece of sh**t, because the vtable is initialized, when the
constructor
> finished successful, so all calls, even the foo() will be static linked
(no
> vpt -
> no dynamic linkage - no surprises with functions called before constructor
> finished)

The question is, how the program tells, in function init(), that vtable isn't yet initialized? Add a bit flag and perform an implicit check for each method call?


March 06, 2002
"Richard Krehbiel" <rich@kastle.com> wrote in message news:a65rol$1aio$1@digitaldaemon.com...

> Now, as a long-time C programmer, I'm willing to sacrifice some safety for power.  But frankly, I'm not seeing how this adds power.  If anyone can
come
> up with a concrete example that shows the power of calling base class methods before calling the base class constructor, I'd appreciate it.

The "base" method could be overridden in this class (easily detectable),
or in one of its descendants (not detectable). So calling it could
be perfectly legal in some context.




March 06, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> schrieb im Newsbeitrag news:3C86780B.1A35A735@deming-os.org...
> I ran across this sort of situation in a library I was developing in C++:
>
> class Worker {...};
> class Thing
> {
> protected:
>     Worker *myWorker;
>
> public:
>     Thing() { myWorker = new Worker };
> }
> class WorkerChild : public Worker {...};
> class ThingChild : public Thing
> {
>    // how do I create a WorkerChild object and pass it to my
>    // parent class?  I want to use WorkerChild as the worker
> }

I do not think, that ThingChild should create the WorkerChild,
since it is not his responsibility (It is the responsibility of the
base class Thing). Maybe a factory-class can do it as a
gray area...

My solution (maybe not the straight-forward-one? ;-):

class Employer {
 ...
    virtual Worker* employ() {return new Worker;}
};
class ChildEmployer {
...
    // if you like, you can make runtime checks to determinate
    // whether a WorkerChild is good or something else.
    Worker* employ() {return new WorkerChild;}
};

class Thing
{
protected:
    Worker *myWorker;
public:
    Thing(const Employer& employer)

         myWorker = employer.employ()
    };
}

class ThingChild : public Thing
: Thing(ChildEmployer())
{}


You see, it is possible without dynamic linkage within the
constructor. Whether it is obvious, a good OO-Model, a
good solution or maybe a bad hack, whe could discuss ;-)

Imi