June 10, 2004
In article <caa5q6$1844$1@digitaldaemon.com>, Marcin says...
>
>Exactly. That's why you can't do it in C++/Java/C#. Altough I prefer C++/C# syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not to call any base portions or it will be undefined, and you have to be careful not to call any methods/functions that will use base poritions or the result will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single line of code in the derived ctor?

Is this even an issue?  Why not just do this:

class A {}

class B
{
this()
{
try { super(); }
catch( Exception e ) { throw new DerivedException(); }
}
}

It seems far cleaner than the function try blocks in C++.


Sean


June 10, 2004
"Sean Kelly" <sean@f4.ca> wrote in message news:caa790$1adj$1@digitaldaemon.com...
> In article <caa5q6$1844$1@digitaldaemon.com>, Marcin says...
> >
> >Exactly. That's why you can't do it in C++/Java/C#. Altough I prefer
C++/C#
> >syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not
to
> >call any base portions or it will be undefined, and you have to be
careful
> >not to call any methods/functions that will use base poritions or the
result
> >will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single
line
> >of code in the derived ctor?
>
> Is this even an issue?  Why not just do this:
>
> class A {}
>
> class B
> {
> this()
> {
> try { super(); }
> catch( Exception e ) { throw new DerivedException(); }
> }
> }
>
> It seems far cleaner than the function try blocks in C++.
>
>
> Sean
>
>

You're missing the big picture. I'm not arguing over which syntax is better. Take a look at this:

class base
{
 private:
 int x;
 public:
 void print()
 {
   printf("%d\n", x);
 }
 this()
 {
  x = 8;
  printf("constructing base\n");
 }
}

class derived : base
{
 this()
 {
  print();
  super();
 }
}

When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is. This must not ever happen. You should really read this: http://www.gotw.ca/gotw/066.htm .


June 10, 2004
In article <caadke$1jmk$1@digitaldaemon.com>, Marcin says...
>
>
>class derived : base
>{
> this()
> {
>  print();
>  super();
> }
>}
>

This is just trying to use an object that wasn't instanciated.
It's the same as:
    base b;
    b.print();
(javac for example will issue an error)

I don't see a big problem with it.

Ant


June 10, 2004
In article <caadke$1jmk$1@digitaldaemon.com>, Marcin says...
>
>You're missing the big picture. I'm not arguing over which syntax is better. Take a look at this:
>
>class base
>{
> private:
> int x;
> public:
> void print()
> {
>   printf("%d\n", x);
> }
> this()
> {
>  x = 8;
>  printf("constructing base\n");
> }
>}
>
>class derived : base
>{
> this()
> {
>  print();
>  super();
> }
>}
>
>When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is. This must not ever happen.

Certainly.  D is a tad different from C++ in that it doesn't require superclasses to be initialized first.  This is fine so long as the user isn't foolish enough to try your example above :)  And I should point out this quote from the D docs:

"If no call to constructors via this or super appear in a constructor, and the base class has a constructor, a call to super() is inserted at the beginning of the constructor."

So assuming the user isn't deliberately foolish then everything will work out fine.  There's really no reason to explicitly call a superclass constructor with no parameters unless you want to catch any exceptions it throws.


Sean


June 10, 2004
In article <caaed0$1km1$1@digitaldaemon.com>, Ant says...
>
>In article <caadke$1jmk$1@digitaldaemon.com>, Marcin says...
>>
>>
>>class derived : base
>>{
>> this()
>> {
>>  print();
>>  super();
>> }
>>}
>
>This is just trying to use an object that wasn't instanciated. It's the same as:
>    base b;
>    b.print();
>(javac for example will issue an error)
>
>I don't see a big problem with it.

This is slightly different.  If a class has a constructor then it's safe to assume that something inside that class requires initialization in order to work properly.  Assuming the class only contains standard D class references and such then the worst that will happen is the runtime error you've mentioned.  But assume for a moment that the class uses pointers, special memory allocators, and all sorts of other weirdness.  In that case the program may crash horribly if a function is called on the class before it is properly initialized.  So in general terms: "the result of calling a function on an unconstructed class instance is undefined."  Usually this means the app will crash but it can also lead to either subtle bugs or crazy stuff like your hard drive being erased. Slightly different from trying to access a null reference :)

Sean


June 10, 2004
In article <caaevs$1llt$1@digitaldaemon.com>, Sean Kelly says...
>
>
>This is slightly different.
[...]
>assume for a moment that the class uses pointers, special memory allocators, and all sorts of other weirdness.
[...]

I see, thanks.
But I still like this feature, I believe I use it somewhere.

Ant


June 10, 2004
In article <caadke$1jmk$1@digitaldaemon.com>, Marcin says...

>When you construct a derived object, you're accessing a function (print) in an object that doesn't exist yet - base. If this isn't a recipe for disaster then I don't know what is.

So don't do it then. It's not compulsory.

Look, you can reason by similar argument that a constructor should not be allowed to call any member function of its own class, because, by definition, if the constructor hasn't returned yet, the object isn't fully constructed yet. Look see:

>   class A
>   {
>       this()
>       {
>           print();
>           printf("finished constructing A\n");
>       }
>
>       void print()
>       {
>           printf("executing A.print()\n");
>       }
>    }

We can all write dumb code. The trick is, not to. As things stand, D constructors are nice and readable, and if you do something dumb you can expect your program to fall over. And that's how it should be.

Compile-time error checking is there to catch the kinds of errors which are NOT obvious. C++ gives you a tortured syntax which make it much harder to figure out construction order. In D you can just SEE it. So I'm not convinced that either the Java way or the C++ way is better. I still think that D has got the better balance between readability and safety, without compromising what you can do.

Arcane Jill


June 10, 2004
Marcin wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message
> news:caa790$1adj$1@digitaldaemon.com...
> 
>>In article <caa5q6$1844$1@digitaldaemon.com>, Marcin says...
>>
>>>Exactly. That's why you can't do it in C++/Java/C#. Altough I prefer
> 
> C++/C#
> 
>>>syntax because it lets you catch base class exceptions and then translate
>>>and rethrow. With D you have to be careful about your member objects not
> 
> to
> 
>>>call any base portions or it will be undefined, and you have to be
> 
> careful
> 
>>>not to call any methods/functions that will use base poritions or the
> 
> result
> 
>>>will be undefined. Wouldn't it be much better and logical if base class
>>>portions were guaranteed to have finished before you can write a single
> 
> line
> 
>>>of code in the derived ctor?
>>
>>Is this even an issue?  Why not just do this:
>>
>>class A {}
>>
>>class B
>>{
>>this()
>>{
>>try { super(); }
>>catch( Exception e ) { throw new DerivedException(); }
>>}
>>}
>>
>>It seems far cleaner than the function try blocks in C++.
>>
>>
>>Sean
>>
>>
> 
> 
> You're missing the big picture. I'm not arguing over which syntax is better.
> Take a look at this:
> 
> class base
> {
>  private:
>  int x;
>  public:
>  void print()
>  {
>    printf("%d\n", x);
>  }
>  this()
>  {
>   x = 8;
>   printf("constructing base\n");
>  }
> }
> 
> class derived : base
> {
>  this()
>  {
>   print();
>   super();
>  }
> }
> 
> When you construct a derived object, you're accessing a function (print) in
> an object that doesn't exist yet - base. If this isn't a recipe for disaster
> then I don't know what is. This must not ever happen. You should really read
> this: http://www.gotw.ca/gotw/066.htm .
Exactly that type of error can also happen in just normal classes as well.
class A
{
int b;
this()
{
	print();
	b=1;
}

void print()
{
assert(b==1);
}

}
Thus I don't see a problem, with the way D does it with super and derived classes.
It actually allows the programmer to do stuff without writing create/inits methods as they are needed in C++.
For me this issue is really a no brainer.
June 10, 2004
"Sean Kelly" <sean@f4.ca> wrote in message news:caa790$1adj$1@digitaldaemon.com...
> In article <caa5q6$1844$1@digitaldaemon.com>, Marcin says...
> >
> >Exactly. That's why you can't do it in C++/Java/C#. Altough I prefer C++/C# syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not to call any base portions or it will be undefined, and you have to be careful not to call any methods/functions that will use base poritions or the result will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single line of code in the derived ctor?
>
> Is this even an issue?  Why not just do this:
>
> class A {}
>
> class B
> {
> this()
> {
> try { super(); }
> catch( Exception e ) { throw new DerivedException(); }
> }
> }
>
> It seems far cleaner than the function try blocks in C++.

It should have the same requirement as in C++, that one cannot leave the ctor body (once an x has been caught) via a return statement, but should require the coder to write a throw expression (even if it's only "throw;")

One thing I find important a lot in C++ is the ability to be able to write and call static methods in the initialiser list. I'd like to be able to do the same prior to calling super(), and I imagine that I probably can at the moment in D. Anyone know?


June 10, 2004
"Marcin" <sixpackguy@earthlink.net> wrote in message news:caadke$1jmk$1@digitaldaemon.com...
>
> "Sean Kelly" <sean@f4.ca> wrote in message news:caa790$1adj$1@digitaldaemon.com...
> > In article <caa5q6$1844$1@digitaldaemon.com>, Marcin says...
> > >
> > >Exactly. That's why you can't do it in C++/Java/C#. Altough I prefer
> C++/C#
> > >syntax because it lets you catch base class exceptions and then translate and rethrow. With D you have to be careful about your member objects not
> to
> > >call any base portions or it will be undefined, and you have to be
> careful
> > >not to call any methods/functions that will use base poritions or the
> result
> > >will be undefined. Wouldn't it be much better and logical if base class portions were guaranteed to have finished before you can write a single
> line
> > >of code in the derived ctor?
> >
> > Is this even an issue?  Why not just do this:
> >
> > class A {}
> >
> > class B
> > {
> > this()
> > {
> > try { super(); }
> > catch( Exception e ) { throw new DerivedException(); }
> > }
> > }
> >
> > It seems far cleaner than the function try blocks in C++.
> >
> >
> > Sean
> >
> >
>
> You're missing the big picture. I'm not arguing over which syntax is better. Take a look at this:
>
> class base
> {
>  private:
>  int x;
>  public:
>  void print()
>  {
>    printf("%d\n", x);
>  }
>  this()
>  {
>   x = 8;
>   printf("constructing base\n");
>  }
> }
>
> class derived : base
> {
>  this()
>  {
>   print();
>   super();
>  }
> }

I agree with what you're saying (and I bet Sean does also).