April 08, 2008
Sorry, for silly question by could anyone give link where I could found how D constructor and destructors works. The behavious is very nice but much different from C++.

import std.stdio;

class A {
	void init()  { writefln("A.init"); }
	void fn()    { writefln("A.fn"); }
	void flush() { writefln("A.flush"); }
	this()       { writefln("A");init(); }
	~this()      { flush();writefln("~A"); }
}

class B : A {
	void init()  { writefln("B.init"); }
	void fn()    { writefln("B.fn"); }
	void flush() { writefln("B.flush"); }
	this() { writefln("B"); }
	~this() { writefln("~B"); }
}

void main() {
	writefln("D1.0 main");
	A a=new B;
	a.fn();
	delete a;
}
/*

D1.0 main
	A
	B.init
	B
	B.fn
	~B
	B.flush
	~A

C++ version
	A
	A.init (no B vft yet)
	B
	B.fn
	A.flush (dtor overrides vft)
	~A

*/

ps: C++ version more strong but hardly usefull. D version looks much better for me. But how it implemented or should be implemented. If ~B already kills his resources?
April 08, 2008
The simple answer is:

Get rid of all your destructors. You don't need them.
Get rid of all your delete statements. You don't need them.

That's pretty much how you write code in D. (D has a garbage collector. It takes care of cleanup for you).
April 08, 2008
D uses virtual functions by default (and C++ does not).  Most of your code is showing virtual function handling vs. non-virtual function handling.

I'm unclear on how flush is getting called at all.

kov_serg Wrote:

> Sorry, for silly question by could anyone give link where I could found how D constructor and destructors works. The behavious is very nice but much different from C++.
> 
> import std.stdio;
> 
> class A {
> 	void init()  { writefln("A.init"); }
> 	void fn()    { writefln("A.fn"); }
> 	void flush() { writefln("A.flush"); }
> 	this()       { writefln("A");init(); }
> 	~this()      { flush();writefln("~A"); }
> }
> 
> class B : A {
> 	void init()  { writefln("B.init"); }
> 	void fn()    { writefln("B.fn"); }
> 	void flush() { writefln("B.flush"); }
> 	this() { writefln("B"); }
> 	~this() { writefln("~B"); }
> }
> 
> void main() {
> 	writefln("D1.0 main");
> 	A a=new B;
> 	a.fn();
> 	delete a;
> }
> /*
> 
> D1.0 main
> 	A
> 	B.init
> 	B
> 	B.fn
> 	~B
> 	B.flush
> 	~A
> 
> C++ version
> 	A
> 	A.init (no B vft yet)
> 	B
> 	B.fn
> 	A.flush (dtor overrides vft)
> 	~A
> 
> */
> 
> ps: C++ version more strong but hardly usefull. D version looks much better for me. But how it implemented or should be implemented. If ~B already kills his resources?

April 08, 2008
Janice Caron wrote:
> The simple answer is:
> 
> Get rid of all your destructors. You don't need them.
> Get rid of all your delete statements. You don't need them.
> 
> That's pretty much how you write code in D. (D has a garbage
> collector. It takes care of cleanup for you).

that only works in most cases where the object only owns memory resources. If it owns files, mutexes, database connections, stock options or Corvettes, your sunk.
April 08, 2008
On 08/04/2008, BCS <BCS@pathlink.com> wrote:
>  that only works in most cases where the object only owns memory resources.
> If it owns files, mutexes, database connections, stock options or Corvettes,
> your sunk.

Yeah, yeah - I know - but kov_serg is a beginner, so I figured, start with the easy. Just get the hang of the marvellous thing that is the garbage collector, and when the day comes when you say "Right then - how do I close I file?", that's when you want to start needing to know about destructors.
April 08, 2008
Every destructor in the hierarchy will be called. I don't recall if you can do something like ~super(), but the default is exactly as you see: bottommost destructor to topmost destructor. flush() in A is being called because ~this() in A calls it.

So, you have to make sure that B's destructor doesn't destroy any data that is in fact owned by its parent class, A. Why would you, though?

However, as Janice mentioned, destructors aren't really that useful in a GC'd language. They're only useful when your class is stapling itself to some lower-level resource, like malloc'd memory or fopen'd files. I don't think I've actually written a destructor in any D code. At all.

 - Gregor Richards


Jason House wrote:
> D uses virtual functions by default (and C++ does not).  Most of your code is showing virtual function handling vs. non-virtual function handling.
> 
> I'm unclear on how flush is getting called at all.
> 
> kov_serg Wrote:
> 
>> Sorry, for silly question by could anyone give link where I could found how D constructor and destructors works. The behavious is very nice but much different from C++. 
>>
>> import std.stdio;
>>
>> class A {
>> 	void init()  { writefln("A.init"); }
>> 	void fn()    { writefln("A.fn"); }
>> 	void flush() { writefln("A.flush"); }
>> 	this()       { writefln("A");init(); }
>> 	~this()      { flush();writefln("~A"); }
>> }
>>
>> class B : A {
>> 	void init()  { writefln("B.init"); }
>> 	void fn()    { writefln("B.fn"); }
>> 	void flush() { writefln("B.flush"); }
>> 	this() { writefln("B"); }
>> 	~this() { writefln("~B"); }
>> }
>>
>> void main() {
>> 	writefln("D1.0 main");
>> 	A a=new B;
>> 	a.fn();
>> 	delete a;
>> }
>> /*
>>
>> D1.0 main
>> 	A
>> 	B.init
>> 	B
>> 	B.fn
>> 	~B
>> 	B.flush
>> 	~A
>>
>> C++ version
>> 	A
>> 	A.init (no B vft yet)
>> 	B
>> 	B.fn
>> 	A.flush (dtor overrides vft)
>> 	~A
>>
>> */
>>
>> ps: C++ version more strong but hardly usefull. D version looks much better for me. But how it implemented or should be implemented. If ~B already kills his resources?
> 
April 09, 2008
"Gregor Richards" <Richards@codu.org> wrote in message news:ftga4f$1gbn$1@digitalmars.com...
> Every destructor in the hierarchy will be called. I don't recall if you can do something like ~super(), but the default is exactly as you see: bottommost destructor to topmost destructor. flush() in A is being called because ~this() in A calls it.
>
> So, you have to make sure that B's destructor doesn't destroy any data that is in fact owned by its parent class, A. Why would you, though?

But it appears B's flush is being called, not A's, and B's data is definately destroyed, because ~B was called before it. Likewise, B's init is called before B's ctor!

I find it all very worrying. It's a good thing I avoid inheritance like the plague lately.

L. 

April 09, 2008
It should always be considered an error to call a virtual member function in a destructor. Someone should make a bug report for this. I would if I was at a computer and not typing with my thumb...

Lionello Lunesu Wrote:

> 
> "Gregor Richards" <Richards@codu.org> wrote in message news:ftga4f$1gbn$1@digitalmars.com...
> > Every destructor in the hierarchy will be called. I don't recall if you can do something like ~super(), but the default is exactly as you see: bottommost destructor to topmost destructor. flush() in A is being called because ~this() in A calls it.
> >
> > So, you have to make sure that B's destructor doesn't destroy any data that is in fact owned by its parent class, A. Why would you, though?
> 
> But it appears B's flush is being called, not A's, and B's data is definately destroyed, because ~B was called before it. Likewise, B's init is called before B's ctor!
> 
> I find it all very worrying. It's a good thing I avoid inheritance like the plague lately.
> 
> L.
> 

April 09, 2008
BCS wrote:
> that only works in most cases where the object only owns memory resources. If it owns files, mutexes, database connections, stock options or Corvettes, your sunk.

Really? I have yet to write a finalize() method in Java. IMO, using close() methods for non-memory resources and letting the GC clean up the memory makes for less cognitive load than worrying about the order of destruction, etc., etc.
April 09, 2008
Lionello Lunesu wrote:
>  It's a good thing I avoid inheritance like
> the plague lately.

Wouldn't it be better to avoid destructors like the plague instead?
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home