digitalmars.D - D classes inherane. How it works.
- kov_serg (40/40) Apr 08 2008 Sorry, for silly question by could anyone give link where I could found ...
- Janice Caron (5/5) Apr 08 2008 The simple answer is:
- BCS (4/11) Apr 08 2008 that only works in most cases where the object only owns memory
- Janice Caron (6/9) Apr 08 2008 Yeah, yeah - I know - but kov_serg is a beginner, so I figured, start
- Robert Fraser (5/8) Apr 08 2008 Really? I have yet to write a finalize() method in Java. IMO, using
- BCS (7/18) Apr 08 2008 My comment was in light of "let the GC handle it". Your suggestion amoun...
- Robert Fraser (3/9) Apr 09 2008 Fair enough, but designing classes such that the order of destruction is...
- Kevin Bealer (28/38) Apr 09 2008 If the relationship from A to B is clear, then one approach is to use a ...
- Jason House (3/51) Apr 08 2008 D uses virtual functions by default (and C++ does not). Most of your co...
- Gregor Richards (12/67) Apr 08 2008 Every destructor in the hierarchy will be called. I don't recall if you
- Lionello Lunesu (8/14) Apr 08 2008 But it appears B's flush is being called, not A's, and B's data is
- Jason House (2/22) Apr 08 2008
- Lionello Lunesu (6/9) Apr 09 2008 I agree, but this would mean that only final, static and global function...
- Jason House (4/18) Apr 10 2008 It's also safe to call private and templated functions.
- Janice Caron (2/3) Apr 10 2008 I suspect you mean "overridden".
- Jason House (2/6) Apr 10 2008 Yes, sorry.
- Robert Fraser (2/3) Apr 10 2008 Indeed. Using the "final" storage class.
- Robert Fraser (2/4) Apr 08 2008 Wouldn't it be better to avoid destructors like the plague instead?
- Lionello Lunesu (7/11) Apr 08 2008 I think there are more problems with inheritance than these "virtual cal...
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?
Apr 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).
Apr 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.
Apr 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.
Apr 08 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.
Apr 08 2008
Reply to Robert,BCS wrote:My comment was in light of "let the GC handle it". Your suggestion amounts to manual memory management (s/memory/resource/). That is fine but to make it work you need to keep track of lifetimes which isn't letting the GC do it. Personally I'd think the way to handle this kind of thing would be to try really hard to make order of destruction irrelevant and let the GC call ~this().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.
Apr 08 2008
BCS wrote:My comment was in light of "let the GC handle it". Your suggestion amounts to manual memory management (s/memory/resource/). That is fine but to make it work you need to keep track of lifetimes which isn't letting the GC do it. Personally I'd think the way to handle this kind of thing would be to try really hard to make order of destruction irrelevant and let the GC call ~this().Fair enough, but designing classes such that the order of destruction is irrelevant is no trivial task.
Apr 09 2008
Robert Fraser Wrote:BCS wrote:If the relationship from A to B is clear, then one approach is to use a static map to store the B objects. This insures that the ordering is preserved. class B { }; class A { this() { data = new B; safety_[data] = 1; } ~this() { data.close(); data.cleanup(); data.flush(); data.etc(); safety_.remove(data); } private: B data; int[B] safety_; }; This delays the destruction of B for another GC cycle, but maybe that's not a big deal. If you know that only A uses B, then you can probably also delete B from A.~this if you like. Beware of cycles, this code wasn't compiled, always ski in control, etc. KevinMy comment was in light of "let the GC handle it". Your suggestion amounts to manual memory management (s/memory/resource/). That is fine but to make it work you need to keep track of lifetimes which isn't letting the GC do it. Personally I'd think the way to handle this kind of thing would be to try really hard to make order of destruction irrelevant and let the GC call ~this().Fair enough, but designing classes such that the order of destruction is irrelevant is no trivial task.
Apr 09 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?
Apr 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?
Apr 08 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.
Apr 08 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.
Apr 08 2008
"Jason House" <jason.james.house gmail.com> wrote in message news:fthbok$vs8$1 digitalmars.com...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...I agree, but this would mean that only final, static and global functions are allowed in ctors/dtors? Would be interesting to add a warning for this, to see how many times it occurs in existing code. L.
Apr 09 2008
It's also safe to call private and templated functions. Private functions, by definition, can't be overloaded. Templated functions are defined to be non-virtual. Does D have final functions? Lionello Lunesu Wrote:"Jason House" <jason.james.house gmail.com> wrote in message news:fthbok$vs8$1 digitalmars.com...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...I agree, but this would mean that only final, static and global functions are allowed in ctors/dtors? Would be interesting to add a warning for this, to see how many times it occurs in existing code. L.
Apr 10 2008
On 10/04/2008, Jason House <jason.james.house gmail.com> wrote:Private functions, by definition, can't be overloaded.I suspect you mean "overridden".
Apr 10 2008
Janice Caron Wrote:On 10/04/2008, Jason House <jason.james.house gmail.com> wrote:Yes, sorry.Private functions, by definition, can't be overloaded.I suspect you mean "overridden".
Apr 10 2008
Jason House wrote:Does D have final functions?Indeed. Using the "final" storage class.
Apr 10 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?
Apr 08 2008
"Robert Fraser" <fraserofthenight gmail.com> wrote in message news:fthlbc$1fro$2 digitalmars.com...Lionello Lunesu wrote:I think there are more problems with inheritance than these "virtual calls in ctor/dtor" : ) I used to be so fond of OOP and its inheritance, but lately I find myself preferring composition and free-functions to "class frameworks". L.It's a good thing I avoid inheritance like the plague lately.Wouldn't it be better to avoid destructors like the plague instead?
Apr 08 2008