D - vpt initialized before constructor?
- Immanuel Scholz (22/22) Mar 05 2002 Hi,
- Walter (15/37) Mar 05 2002 What happens is a static initializer is prepared for each class. Memory ...
- Immanuel Scholz (11/20) Mar 05 2002 is
- Pavel Minayev (10/15) Mar 05 2002 If you forbid constructor to modify member variables, it simply
- Immanuel Scholz (12/27) Mar 06 2002 value.
- Pavel Minayev (13/19) Mar 06 2002 D doesn't have const and non-const functions, because D doesn't
- Immanuel Scholz (15/34) Mar 06 2002 Hmm... Yes.
- Pavel Minayev (21/28) Mar 06 2002 Const functions operate only on const objects. And you cannot have
- Immanuel Scholz (21/51) Mar 06 2002 Hm... I do not understand, why this should be a problem.
- Pavel Minayev (13/24) Mar 06 2002 to
- Immanuel Scholz (6/13) Mar 08 2002 Isn't it a disadvantage to loose the type safety provided by declaring
- Pavel Minayev (8/10) Mar 08 2002 I don't really see much reason in it. In C++, the most obvious
- Walter (19/29) Mar 09 2002 My experience with const as a type modifier is it:
- Richard Krehbiel (49/49) Mar 06 2002 (Not in reply to any particular person - I'm just clarifying this issue ...
- Russ Lewis (27/31) Mar 06 2002 I ran across this sort of situation in a library I was developing in C++...
- Immanuel Scholz (33/48) Mar 06 2002 I do not think, that ThingChild should create the WorkerChild,
- Rchard Krehbiel (18/38) Mar 06 2002 for
- Russ Lewis (21/27) Mar 06 2002 Right, that's exactly what I did. But it didn't work because I had to i...
- Sean L. Palmer (9/16) Mar 07 2002 implement
- Russ Lewis (14/17) Mar 07 2002 I remember having a problem with this. Frankly, I don't remember if the
- Sean L. Palmer (21/33) Mar 07 2002 this
- Pavel Minayev (4/6) Mar 07 2002 Absolutely. AFAIK it doesn't even require the base constructor
-
Walter
(3/5)
Mar 09 2002
I've heard that some european laws make that very difficult
. - OddesE (10/15) Mar 11 2002 LOL!
- Pavel Minayev (6/10) Mar 06 2002 come
- Walter (32/49) Mar 09 2002 Yes.
- OddesE (18/65) Mar 05 2002 is
- Immanuel Scholz (25/31) Mar 05 2002 Yes, you miss something:
- Pavel Minayev (28/48) Mar 05 2002 YES!
- Immanuel Scholz (28/37) Mar 05 2002 HA! And here is the point I want to show.
- Pavel Minayev (30/39) Mar 05 2002 Functions always exist. They, however, might rely on the data that wasn'...
- Immanuel Scholz (52/81) Mar 05 2002 hWnd -
- Walter (19/47) Mar 05 2002 You've just described the problem resolved by the class invariant!
- Immanuel Scholz (86/130) Mar 05 2002 variables
- Walter (13/64) Mar 05 2002 Generally, yes, though this is individually controllable. And it is a
- Immanuel Scholz (57/112) Mar 06 2002 manual
- Pavel Minayev (22/35) Mar 06 2002 things.
- Immanuel Scholz (56/92) Mar 06 2002 Most functions that depend on initialised members
- Pavel Minayev (22/72) Mar 06 2002 Just don't call such functions from the point where
- Immanuel Scholz (115/195) Mar 06 2002 GRRR! Am I talking to a wall? :-|
- Pavel Minayev (39/56) Mar 06 2002 ...the wall being asked? =)
- Immanuel Scholz (29/69) Mar 06 2002 be
- Pavel Minayev (3/12) Mar 06 2002 Exactly. And BTW that's the way I do it. =)
-
OddesE
(21/45)
Mar 06 2002
"Immanuel Scholz"
wrote in message - Immanuel Scholz (16/27) Mar 06 2002 Yeah. It works for many cases. It does not work for
- Pavel Minayev (3/10) Mar 06 2002 Yes, yes!!! =)
- Walter (10/13) Mar 09 2002 A probably more accurate statement would be that the assert expression m...
- Pavel Minayev (4/8) Mar 09 2002 must
- Roberto Mariottini (8/16) Mar 11 2002 to
- Pavel Minayev (3/4) Mar 11 2002 There are no const functions...
- OddesE (64/64) Mar 06 2002 Dear Immanuel,
- Immanuel Scholz (18/50) Mar 06 2002 The construct of calling a virual function from a constructor
- Pavel Minayev (8/11) Mar 06 2002 Static printf() in Object was a bug, AFAIK, and was removed
-
Walter
(17/18)
Mar 06 2002
I should put this in the FAQ
. - Immanuel Scholz (11/22) Mar 07 2002 to
- Pavel Minayev (6/10) Mar 07 2002 The suggested form is:
- Immanuel Scholz (4/15) Mar 08 2002 oh. I thought unnamed parameter were not allowed in D?
- Pavel Minayev (6/7) Mar 08 2002 For some reason, they are currently forbidden in function
Hi, hm, if I got it right: - the vp-table is initialized, and the members are set to something static before the constructor is called - you can call funktions from within the construktor. These are dynamically linked (since the vpt exist). This means, that within any member-function, there could be 2 states: - The own constructor could be completed successfull - all is ok - The function is called from a constructor (or a function the constructor called...). This means, the member-variables are initialized with default values, given at compile time. Isn't this bad? - Either I assume the default values for members are alright and valid - so I need no constructor at all and can take this() {} out of language? - Or I assume, static linked default values are not enough, but members will be filled within the constructor - so I have to check the members in each member-function whether they already initialized or not. Are there a solution? Imi
Mar 05 2002
What happens is a static initializer is prepared for each class. Memory is allocated and the static initializer is copied over it. Then, the constructor is called. This ensures that within the constructor the object is in a defined state, virtual functions can be called, and all members are initialized to the default value. For many (if not most) classes, this is sufficient and it is not even necessary to have a constructor. It guarantees no more bugs due to adding a member and forgetting to initialize it in one of the constructors. Constructors are only necessary if any dynamic initialization is needed. "Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a630s6$241$1 digitaldaemon.com...Hi, hm, if I got it right: - the vp-table is initialized, and the members are set to something static before the constructor is called - you can call funktions from within the construktor. These aredynamicallylinked (since the vpt exist). This means, that within any member-function, there could be 2 states: - The own constructor could be completed successfull - all is ok - The function is called from a constructor (or a function the constructor called...). This means, the member-variables are initialized with default values, given at compiletime.Isn't this bad? - Either I assume the default values for members are alright and valid -soI need no constructor at all and can take this() {} out of language? - Or I assume, static linked default values are not enough, but memberswillbe filled within the constructor - so I have to check the members in each member-function whether they already initialized or not. Are there a solution? Imi
Mar 05 2002
"Walter" <walter digitalmars.com> schrieb im Newsbeitrag news:a634fp$3p4$1 digitaldaemon.com...What happens is a static initializer is prepared for each class. Memory is allocated and the static initializer is copied over it. Then, the constructor is called. This ensures that within the constructor the object is in a defined state, virtual functions can be called, and all members are initialized to the default value. For many (if not most) classes, this is sufficient and itisnot even necessary to have a constructor. It guarantees no more bugs duetoadding a member and forgetting to initialize it in one of theconstructors.Constructors are only necessary if any dynamic initialization is needed.This happens due you presume that a "defined state" is some static value. So you could consider to forbid the constructor to alter the member variables and only allow static pre-constructor-constructs? This means, the problem (stated best in the other posting to Pavel) vanished, but many coders will kill you for this ;) Imi
Mar 05 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a636cb$4fo$1 digitaldaemon.com...This happens due you presume that a "defined state" is some static value. So you could consider to forbid the constructor to alter the member variables and only allow static pre-constructor-constructs? This means, the problem (stated best in the other posting to Pavel) vanished, but many coders will kill you for this ;)If you forbid constructor to modify member variables, it simply loses sense... moreover, it is easy overridden by: class Foo { int bar; this() { init(); } // I don't modify anything... init() { bar = 666; } // muhahahahahaha! =) }
Mar 05 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a637u0$57f$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a636cb$4fo$1 digitaldaemon.com...value.This happens due you presume that a "defined state" is some staticOf course, then the constructor have no rights to call non-const member functions ;-)So you could consider to forbid the constructor to alter the member variables and only allow static pre-constructor-constructs? This means, the problem (stated best in the other posting to Pavel) vanished, but many coders will kill you for this ;)If you forbid constructor to modify member variables, it simply loses sense... moreover, it is easy overridden by:class Foo { int bar; this() { init(); } // I don't modify anything... init() { bar = 666; } // muhahahahahaha! =) }I was joking. Of course it would be a bad idea to forbid the constructor to alter members. But I would state, that it is also a joke to blindly assume, that static values to variables are enough of initialisation. Maybe if the constructor is only allowed to call "final" - member functions? Imi
Mar 06 2002
"Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message news:a65256$vqj$1 digitaldaemon.com...Of course, then the constructor have no rights to call non-const member functions ;-)D doesn't have const and non-const functions, because D doesn't have const objects. How'd you declare them in D anyhow?But I would state, that it is also a joke to blindly assume, that static values to variables are enough of initialisation.Definitely not. That's what the constructor is for.Maybe if the constructor is only allowed to call "final" - memberfunctions? So what? class Foo { this() { init(); } final void init() { foo(); } void foo() { ... } }
Mar 06 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a659c9$12o6$1 digitaldaemon.com..."Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message news:a65256$vqj$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...Of course, then the constructor have no rights to call non-const member functions ;-)D doesn't have const and non-const functions, because D doesn't have const objects. How'd you declare them in D anyhow?Ack. So it is too bad to have that hole (as stated in this thread) in D.But I would state, that it is also a joke to blindly assume, that static values to variables are enough of initialisation.Definitely not. That's what the constructor is for.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 to ignore this problem will make me to not look any futher on D, because I do not believe you could write a library as like as QT or MFC on such a base without ever and ever checking member-variables in functions :-( ) ImiMaybe if the constructor is only allowed to call "final" - memberfunctions? So what? class Foo { this() { init(); } final void init() { foo(); } void foo() { ... } }
Mar 06 2002
"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 requiredOh dear, you are right. So this makes no sense too.. I become thinking that static linkage within constructors is the best solution (The solutionIs 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! =)
Mar 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...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? ;-)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 requiredsolutionOh dear, you are right. So this makes no sense too.. I become thinking that static linkage within constructors is the best solution (TheIs 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)
Mar 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 forbidsto// call non-const functions (e.g. operator= is non-const) const Object baz = new Object; // the object baz is only initializedonce,// 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 theconstructorfinished successful, so all calls, even the foo() will be static linked(novpt - 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?
Mar 06 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a65ub0$1blo$1 digitaldaemon.com...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.Isn't it a disadvantage to loose the type safety provided by declaring something const? What was the reason for this decission?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?Err. Ok, I confuse "static-linkage" a bit with "vpt not completly build up". Imi
Mar 08 2002
"Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message news:a6a72b$q9c$1 digitaldaemon.com...Isn't it a disadvantage to loose the type safety provided by declaring something const? What was the reason for this decission?I don't really see much reason in it. In C++, the most obvious reason for const would be const references (const Object& foo), to allow passing of temporaries created in the process of type conversions. Since there are no such things in D, the need for const is not high. I'm sure Walter might add something to this... =)
Mar 08 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a6a8jv$quo$1 digitaldaemon.com..."Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message news:a6a72b$q9c$1 digitaldaemon.com...My experience with const as a type modifier is it: 1) has confusing syntax & semantics 2) does not enable any better code to be generated (for various technical reasons) 3) needs to be subverted anyway with "mutable" 4) adds a lot of complexity to overload resolution 5) causes declarations to be peppered with "const", reducing readability 6) I haven't seen any convincing data that using them reduces bugs 7) adds unreasonable complexity to the typing system So, it is not in D. const *is* useful as a storage class, as it: 1) enables compile time constant folding 2) enables data to be placed in ROM So, D supports const as a storage class, not as a type modifier. One consequence of this is, as Pavel pointed out, that class objects cannot be const, because class objects can only be created on the garbage collected heap.Isn't it a disadvantage to loose the type safety provided by declaring something const? What was the reason for this decission?I don't really see much reason in it. In C++, the most obvious reason for const would be const references (const Object& foo), to allow passing of temporaries created in the process of type conversions. Since there are no such things in D, the need for const is not high. I'm sure Walter might add something to this... =)
Mar 09 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)
Mar 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))) ]
Mar 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
Mar 06 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C86780B.1A35A735 deming-os.org...Richard Krehbiel wrote:forNow, as a long-time C programmer, I'm willing to sacrifice some safetycomepower. But frankly, I'm not seeing how this adds power. If anyone canWell... If you can change the Thing class, then add a separate constructor which takes a Worker*. But if you can't, then maybe you could destroy the Worker that Thing::Thing() created, and implant your replacement. Well, that may be inefficient, or worse, the original Worker may have caused some undesirable side effect. In either case, yes, I can see how it would might have been a boon to be able to *not* call the Thing constructor at all. Now, I don't know who wrote your Thing class, but maybe it was intended that Worker not be replaceable. After all, what if Thing were designed like this? class Worker { }; class Thing { Worked worker; } It would have been more obvious that you were stuck without an option.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 }
Mar 06 2002
Rchard Krehbiel wrote:Well... If you can change the Thing class, then add a separate constructor which takes a Worker*.Right, that's exactly what I did. But it didn't work because I had to implement the ThingChild constructor like this: ThingChild::ThingChild() : Thing( new WorkerChild ) {...} And different compilers differ on whether that 'new WorkerChild' causes a new object to be created for every ThingChild::ThingChild, or if the same WorkerChild (created once at runtime) is passed every time, or if the whole thing was legal at all. Now, with D, I can do this: ThingChild::this() { super( new WorkerChild ); }; and the code is 100% clear what it means.In either case, yes, I can see how it would might have been a boon to be able to *not* call the Thing constructor at all. Now, I don't know who wrote your Thing class, but maybe it was intended that Worker not be replaceable.I wrote both classes, so I can't blame anybody but me :-0 I intended to replace Worker...but never realized how hard it would be :( -- 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))) ]
Mar 06 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C8698CB.61C5ECAC deming-os.org...Right, that's exactly what I did. But it didn't work because I had toimplementthe ThingChild constructor like this: ThingChild::ThingChild() : Thing( new WorkerChild ) {...} And different compilers differ on whether that 'new WorkerChild' causes anewobject to be created for every ThingChild::ThingChild, or if the same WorkerChild (created once at runtime) is passed every time, or if thewholething was legal at all.Really? Which compiler(s)? I've never seen one that couldn't handle this properly, though I've only used Borland, Watcom, VC++ 4 thru 7, GCC, and CodeWarrior. Sean
Mar 07 2002
"Sean L. Palmer" wrote:Really? Which compiler(s)? I've never seen one that couldn't handle this properly, though I've only used Borland, Watcom, VC++ 4 thru 7, GCC, and CodeWarrior.I remember having a problem with this. Frankly, I don't remember if the problem was that I found compilers with varying outputs, if I just couldn't find a spec, or what. Maybe I'm nuts, and all compilers are the same...but if so, I don't have any idea what the spec is, and it's not obvious from the language construction. So, bascially, I may be totally wrong about C++. If so, I'm sorry. I still think that calling super() inside the function body is a better way to do things. -- 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))) ]
Mar 07 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C879F11.7CBD799C deming-os.org..."Sean L. Palmer" wrote:thisReally? Which compiler(s)? I've never seen one that couldn't handlecouldn'tproperly, though I've only used Borland, Watcom, VC++ 4 thru 7, GCC, and CodeWarrior.I remember having a problem with this. Frankly, I don't remember if the problem was that I found compilers with varying outputs, if I justfind a spec, or what. Maybe I'm nuts, and all compilers are thesame...but ifso, I don't have any idea what the spec is, and it's not obvious from the language construction. So, bascially, I may be totally wrong about C++. If so, I'm sorry. I still think that calling super() inside the function body is a betterway todo things.I agree... it's the way we used to do things back in the old days using Borland Pascal. I think Delphi still works this way. It makes a constructor more like an ordinary virtual function that's been overridden. As with any such function, the overridden version gets control first, does what it has to do, (possibly) calls the inherited version, does any final work, then returns. You always have to do before the call to inherited function what needs to be done before the inherited function is called, and afterward what needs done afterwards. If you want to change its inputs you do it before, and if you want to change its outputs you do it after, usually. But there's no hard and fast rule about it, you just do it in the way that works. If it doesn't work you did it the wrong way. I don't mind shooting myself in the foot once in a while... it keeps me awake. I'd rather have a more flexible language than one that prevents me from being bad. It's good to be bad sometimes. ;) Sean
Mar 07 2002
"Sean L. Palmer" <spalmer iname.com> wrote in message news:a68c6n$2f91$1 digitaldaemon.com...I agree... it's the way we used to do things back in the old days using Borland Pascal. I think Delphi still works this way.Absolutely. AFAIK it doesn't even require the base constructor to be called (which is definitely not the best idea)!
Mar 07 2002
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C8698CB.61C5ECAC deming-os.org...I intended to replace Worker...but never realized how hard it would be :(I've heard that some european laws make that very difficult <g>.
Mar 09 2002
"Walter" <walter digitalmars.com> wrote in message news:a6dp5h$2e8g$1 digitaldaemon.com..."Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message news:3C8698CB.61C5ECAC deming-os.org...LOL! :) Especially Dutch labour laws :) -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mailI intended to replace Worker...but never realized how hard it would be :(I've heard that some european laws make that very difficult <g>.
Mar 11 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 cancomeup 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.
Mar 06 2002
"Richard Krehbiel" <rich kastle.com> wrote in message news:a65rol$1aio$1 digitaldaemon.com...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.Yes.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. The point is to enable the most derived constructor to completely control the construction of the base classes. I find the base class initialization syntax of C++ to be inflexible. If you've ever tried to call a base constructor with a non-trivial computation on its arguments, you know what I mean.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'sstaticconstructors "happen" before any .this() is called.Yes.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 cancomeup with a concrete example that shows the power of calling base class methods before calling the base class constructor, I'd appreciate it.Ok, here's an example: this(int a, int b, int c) { ... computation ... if (condition) super(a,b); else super(c,d); } Or how about: this() { ... basic construction ... } this(int a) { this(); // do basic construction ... more advanced construction ... } Neither can be done without some falderal in C++.
Mar 09 2002
"Walter" <walter digitalmars.com> wrote in message news:a634fp$3p4$1 digitaldaemon.com...What happens is a static initializer is prepared for each class. Memory is allocated and the static initializer is copied over it. Then, the constructor is called. This ensures that within the constructor the object is in a defined state, virtual functions can be called, and all members are initialized to the default value. For many (if not most) classes, this is sufficient and itisnot even necessary to have a constructor. It guarantees no more bugs duetoadding a member and forgetting to initialize it in one of theconstructors.Constructors are only necessary if any dynamic initialization is needed. "Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a630s6$241$1 digitaldaemon.com...staticHi, hm, if I got it right: - the vp-table is initialized, and the members are set to somethingconstructorbefore the constructor is called - you can call funktions from within the construktor. These aredynamicallylinked (since the vpt exist). This means, that within any member-function, there could be 2 states: - The own constructor could be completed successfull - all is ok - The function is called from a constructor (or a function theAnd even then it shouldn't be a problem. *You* make the constructor of your class, so you know which functions it calls. Only these functions may not assume a completed constructor on it's call. Or am I missing something? -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mailcalled...). This means, the member-variables are initialized with default values, given at compiletime.Isn't this bad? - Either I assume the default values for members are alright and valid -soI need no constructor at all and can take this() {} out of language? - Or I assume, static linked default values are not enough, but memberswillbe filled within the constructor - so I have to check the members in each member-function whether they already initialized or not. Are there a solution? Imi
Mar 05 2002
"OddesE" <OddesE_XYZ hotmail.com> schrieb im Newsbeitrag news:a63ehb$81k$1 digitaldaemon.com...Yes, you miss something: class Base_with_no_source_code_access { this() { foo(); } int foo() {} } class My_class_which_I_know_very_well { this() { super(); /* do some initialisation important to the class */ } int foo() { /* do something, that rely on an initialized class */ } } Got it? Even I do not call foo() from within my class, it is called in the base classes constructor - and this before I could initialize the members. (Generally putting super() at the end of constructor is even worse, I think you realize that already ;-). In C++, this is not possible, because a virtual function is not dynamically linked within the constructor. So there, the Base..::foo() would be called instead (and bring its own suprise to programmers ;-) ImiAnd even then it shouldn't be a problem. *You* make the constructor of your class, so you know which functions it calls. Only these functions may not assume a completed constructor on it's call. Or am I missing something?Are there a solution?
Mar 05 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a630s6$241$1 digitaldaemon.com...Hi, hm, if I got it right: - the vp-table is initialized, and the members are set to something static before the constructor is calledYES!- you can call funktions from within the construktor. These aredynamicallylinked (since the vpt exist).YES!!!This means, that within any member-function, there could be 2 states: - The own constructor could be completed successfull - all is ok - The function is called from a constructor (or a function the constructor called...). This means, the member-variables are initialized with default values, given at compiletime.Isn't this bad?No. You should design your interface and implementations in such a manner that things like that don't happen - or at least if they do, it's your responsibility to ensure proper work. There might be a function that doesn't rely on object variables, but rather changes them: class Foo { int bar; this(int n) { init(1); ... } this(float f) { init(2); ... void init(n) { bar = n * n; } } Definitely a stupid, meaningless example... yet it shows that everything might not be that bad.- Either I assume the default values for members are alright and valid -soI need no constructor at all and can take this() {} out of language?Constructor has duties other than assigning values to members. It might perform special specialization routines. For example, the Window class might want to call CreateWindowEx in its constructor.- Or I assume, static linked default values are not enough, but memberswillbe filled within the constructor - so I have to check the members in each member-function whether they already initialized or not.Just don't call member functions that rely on class variables from the constructor.
Mar 05 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a634lr$3qf$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in messageHA! And here is the point I want to show. In C++ of course you can call to member-functions from within the constructor too. But since they are static linked, you may only be aware of functions, that your own constructor in your own class call. In D member functions may be called from constructors you didn't even know they exist, so you live with the bad feeling in your stomach, whether this function may be called before the own constructor finished? Example: class foo : public bar { int x = 0; this {super(); x = calculate_x_right();} int foobar() { // here you cannot be sure, that x contains a right value (returned from // calculate_x_right), because the class bar may define int foobar() and // call it within its constructor... // all you can do is check it (but not with an assertion, because it may // depend on runtime-things whether foobar is called in a superclass) if (x != 0) ... } The check for x != 0 stinks, but you can't really go without it, unless you check the whole hirachy from foo upwards and this may be impossible. Imi- Or I assume, static linked default values are not enough, but memberswillbe filled within the constructor - so I have to check the members in each member-function whether they already initialized or not.Just don't call member functions that rely on class variables from the constructor.
Mar 05 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a635ug$49p$1 digitaldaemon.com...HA! And here is the point I want to show. In C++ of course you can call to member-functions from within the constructor too. But since they are static linked, you may only be aware of functions, that your own constructor in your own class call. In D member functions may be called from constructors you didn't even know they exist, so you live with the bad feeling in your stomach, whether this function may be called before the own constructor finished?Functions always exist. They, however, might rely on the data that wasn't yet properly initialized. For example the constructor of Window might call a caption() method, which'd in turn call SetWindowText, passing hWnd - which is still 0. Yes, it is possible. But it is something YOU should control. It's a usual consistency-vs-usability tradeoff. C++ constructors are very inconvenient, especially when it is required to call the base constructor with different arguments depending on what you get. It usually turns out to be something like: class Foo: public Bar { Foo(int n): Bar(n == 0 ? 1 : n == 1 ? 5 : n == 2 ? 10 : ...) { ... } } In D it can be written much cleaner: class Foo: Bar { this(int n) { switch (n) { case 0: super(1); return; case 1: super(5); return; ... } } } While this method has some quirks that you've mentioned, it is (IMO) much more practical. As long as you don't do "bad" things, the code is way more readable and flexible.
Mar 05 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a638a2$5ai$1 digitaldaemon.com...Functions always exist. They, however, might rely on the data that wasn't yet properly initialized. For example the constructor of Window might call a caption() method, which'd in turn call SetWindowText, passinghWnd -which is still 0. Yes, it is possible. But it is something YOU should control.If I control class Window (to recognize the fact) and the class that redefine caption() (to include the check to hWnd) all is ok. But since I even don't know Window calls to caption, I usually have to check all variables in all functions before assuming, they have a value, that they get in the constructor. So you get no guarantee in any of you member-functions, that one of the constructors finished correctly. And this is IMHO a big disadvantage compared to C++. I tend to layout my Classes, that initializing is done within the constructor, so I can depend on a fully initialized class (not only static copied one) and do not have to check for validness on start on each member function. Maybe this tends to code like: class bar { this {init();} void init () { /* do the real init-stuff here */ } bool is_valid() { /* checks if initialized */ } f1 () {if (!is_valid()) init(); ...} // this first line appear in each function f2 () {if (!is_valid()) init(); ...} // which depends on a valid constructor-run f3 () {if (!is_valid()) init(); ...} f4 () {if (!is_valid()) init(); ...} } And worse: You can't use something like in{} and assert(bar) for this, since it may depend on runtime-decisions whether bar is initialized on call to a member or not. And worst: I think the real problem is deeper, because not everyone sees the problem behind this and may blindly depends on the fact, that the constructor is already passed successfully. And you need some luck to find such a bug in short time.It's a usual consistency-vs-usability tradeoff. C++ constructors are very inconvenient, especially when it is required to call the base constructor with different arguments depending on what you get. It usually turns out to be something like: class Foo: public Bar { Foo(int n): Bar(n == 0 ? 1 : n == 1 ? 5 : n == 2 ? 10 : ...){ ... }} In D it can be written much cleaner: class Foo: Bar { this(int n) { switch (n) { case 0: super(1); return; case 1: super(5); return; ... } } }This is a different issue? Or how it is connected to my problem? It is no problem to call the base classes constructor at any other time, as long as these base class Bar cannot call any member-function within Foo before Foo.init() is finished! But anyway: Did you ensure (maybe with an warning, that can be turned to an error) that the user did not simple forget calling the base-constructor?While this method has some quirks that you've mentioned, it is (IMO) much more practical. As long as you don't do "bad" things, the code is way more readable and flexible.<GRHN!> I disagree! It is not me who has to do no "bad things". It is the writer of my base classes! They should not be able to call my functions before my constructor finish. And I cannot access the source of my base-classes (either because I cannot or won't or shouldn't or have such time). Maybe all functions a constructor call (and all functions this function calls...) has to be final and cannot overidden? This might be a solution. Imi
Mar 05 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a63a8a$68f$1 digitaldaemon.com...If I control class Window (to recognize the fact) and the class that redefine caption() (to include the check to hWnd) all is ok. But since I even don't know Window calls to caption, I usually have to check all variables in all functions before assuming, they have a value, that they get in the constructor.You've just described the problem resolved by the class invariant!So you get no guarantee in any of you member-functions, that one of the constructors finished correctly. And this is IMHO a big disadvantage compared to C++.C++ has a terrible disadvantage in that there's no guarantee there's any value other than garbage in any member. I can't even count the number of times I've had a bug where I added a member and then forgot to initialize it in one of the many constructors for it. With D, you have: 1. all members are guaranteed to at least contain their static default values. 2. you can use preconditions on a function to guarantee specific values. 3. you can use class invariants to guarantee correct construction before public member functions get called. None of this is supported by C++.class bar { this {init();} void init () { /* do the real init-stuff here */ } bool is_valid() { /* checks if initialized */ } f1 () {if (!is_valid()) init(); ...} // this first line appear in each function f2 () {if (!is_valid()) init(); ...} // which depends on a valid constructor-run f3 () {if (!is_valid()) init(); ...} f4 () {if (!is_valid()) init(); ...} }The "is_valid()" function is analogous to the D class invariant, except with D the class invariant call is automatically inserted (and inherited).And worse: You can't use something like in{} and assert(bar) for this, since it may depend on runtime-decisions whether bar is initialized on call to a member or not.I don't see how.And worst: I think the real problem is deeper, because not everyone sees the problem behind this and may blindly depends on the fact, that the constructor is already passed successfully. And you need some luck to find such a bug in short time.D has both more flexibility in constructor design and more inherent robustness. You can add initialization guarantees using the class invariant.
Mar 05 2002
"Walter" <walter digitalmars.com> schrieb im Newsbeitrag news:a63duu$7q1$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a63a8a$68f$1 digitaldaemon.com...variablesIf I control class Window (to recognize the fact) and the class that redefine caption() (to include the check to hWnd) all is ok. But since I even don't know Window calls to caption, I usually have to check allthein all functions before assuming, they have a value, that they get inHm. I do not think so. Class invariants are, as long as I read the manual right, only compiled into the debug version. But the decission, whether a inherited function is called could be at runtime: class B { this () { if (/* User is unhappy with the programm */) foo(); } int foo(); } class D : B { this() {} int foo(); // is this function called only after constructor finished? }constructor.You've just described the problem resolved by the class invariant!itSo you get no guarantee in any of you member-functions, that one of the constructors finished correctly. And this is IMHO a big disadvantage compared to C++.C++ has a terrible disadvantage in that there's no guarantee there's any value other than garbage in any member. I can't even count the number of times I've had a bug where I added a member and then forgot to initializein one of the many constructors for it.Those problems are on an other page! I am disagree with resolving function linkage through the vpt within constructors, not preinitialize members. Maybe with preinitializing, you can ommit some or most constructors, but you cannot go around the dynamic-linkage-within-constructors-problem.With D, you have: 1. all members are guaranteed to at least contain their static default values.Wonderful! I missed this one in C++ due lack of sense for typical error situations from the C++-Authority (these are alltogether performance- sharks ;-).2. you can use preconditions on a function to guarantee specific values.Only in debug! So this is almost useless against unknown source guarantees.3. you can use class invariants to guarantee correct construction before public member functions get called.Also only in debug-mode. Theese are all suits pretty when coding and fast finding errors, but IMHO it cannot replace a good scheme of guarantees on runtime!None of this is supported by C++.hm, somewhat.. you can emulate it, but not use it directly, thats right. So D is not more powerful, but much easier to use on those. (But thats not my problem in this thread)withclass bar { this {init();} void init () { /* do the real init-stuff here */ } bool is_valid() { /* checks if initialized */ } f1 () {if (!is_valid()) init(); ...} // this first line appear in each function f2 () {if (!is_valid()) init(); ...} // which depends on a valid constructor-run f3 () {if (!is_valid()) init(); ...} f4 () {if (!is_valid()) init(); ...} }The "is_valid()" function is analogous to the D class invariant, exceptD the class invariant call is automatically inserted (and inherited)....and removed on release-build. BTW: I thought the invariant are only looked after if you call to assert(b); (and b is from type bar)? So it might be usable, if you provide such a valid- check and let the "compile-invariant-switch" for those classes on... But even then: It is not good to give the burden for this workaround to the programmer.e.g. it could depend on some registry-entries, whether a function is called or not: class B { this() { if (/* there are some interesting registry entries */) foo(); } int foo(); } class D : B { int foo() in { /* check for validation is useless, since on the test-system, there might be no those registry entries */ } body { /* although I checked in the "in"-section, I can not be sure, that D is initialized proper (means -> D.this() is called successfull) */ } } Of course, you alwasy can blame it to a bad testbed... but I would blame it to a trap-hard-to-find-but-easy-to-step-into.And worse: You can't use something like in{} and assert(bar) for this, since it may depend on runtime-decisions whether bar is initialized on call to a member or not.I don't see how.D has both more flexibility in constructor design and more inherent robustness. You can add initialization guarantees using the classinvariant. So you keep it to the user to realize, that there might be a problem, if he depends on successfull constructor finishing. (And you need to let the invariant-checks compiled in, even in release) On the other hand, if D implements a static linkage within the constructor (like in C++), many programmer would get into trouble with this inconsistency. And sometimes it come in handy to call a virtual function from within constructors... Are you planning to include a keyword like the java's "final" ? Why not? And what about one to say: "This function may not overwrite an other!" ? So you can at least do some basic protection against the problem in this thread (when you realized, there is a problem) Imi
Mar 05 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a63h9j$9e1$1 digitaldaemon.com..."Walter" <walter digitalmars.com> schrieb im Newsbeitrag news:a63duu$7q1$1 digitaldaemon.com...Generally, yes, though this is individually controllable. And it is a debugging issue, not an error to be dealt with in released code."Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a63a8a$68f$1 digitaldaemon.com...variablesIf I control class Window (to recognize the fact) and the class that redefine caption() (to include the check to hWnd) all is ok. But since I even don't know Window calls to caption, I usually have to check allthein all functions before assuming, they have a value, that they get inHm. I do not think so. Class invariants are, as long as I read the manual right, only compiled into the debug version.constructor.You've just described the problem resolved by the class invariant!But the decission, whether a inherited function is called could be at runtime: class B { this () { if (/* User is unhappy with the programm */) foo(); } int foo(); } class D : B { this() {} int foo(); // is this function called only after constructor finished? }That is a good point. You can guard against that by using a class invariant in D.foo(), or by calling foo() using the direct syntax: B.foo();Maybe with preinitializing, you can ommit some or most constructors, but you cannot go around the dynamic-linkage-within-constructors-problem.Ok, I understand your point now.I *really* wanted to fix that one, having had so many bugs due to it.With D, you have: 1. all members are guaranteed to at least contain their static default values.Wonderful! I missed this one in C++ due lack of sense for typical error situations from the C++-Authority (these are alltogether performance- sharks ;-).You can still leave it on the release code.2. you can use preconditions on a function to guarantee specific values.Only in debug! So this is almost useless against unknown source guarantees.Again, you can leave that stuff turned on.3. you can use class invariants to guarantee correct construction before public member functions get called.Also only in debug-mode. Theese are all suits pretty when coding and fast finding errors, but IMHO it cannot replace a good scheme of guarantees on runtime!SoNone of this is supported by C++.hm, somewhat.. you can emulate it, but not use it directly, thats right.D is not more powerful, but much easier to use on those. (But thats not my problem in this thread)<g> All of C++'s features can be emulated in C, after all.
Mar 05 2002
"Walter" <walter digitalmars.com> schrieb im Newsbeitrag news:a63puv$e0l$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in messagemanualHm. I do not think so. Class invariants are, as long as I read theRight. You should never forced to use debugging tools for release - things. So all you can do is to add your own "invariant" - code in each function that depend on an correctly, dynamically initialized member.right, only compiled into the debug version.Generally, yes, though this is individually controllable. And it is a debugging issue, not an error to be dealt with in released code.finished?But the decission, whether a inherited function is called could be at runtime: class B { this () { if (/* User is unhappy with the programm */) foo(); } int foo(); } class D : B { this() {} int foo(); // is this function called only after constructorinvariant}That is a good point. You can guard against that by using a classin D.foo(),But as I stated above, class invariants are not for testing runtime- conditions, but to debug and find static-conditions (errors in code, not in enviroment).or by calling foo() using the direct syntax: B.foo();In my szenario, you have no control over the constructor of B. This is real, because it might be deep in a gui-library (as example MFC).I hope you do something against that, I think it is not just a constructed problem, that very seldom to never occours. I think it could be become typical, since user begin to allocate the memory for their pointers within constructor: class bar : foo { ptr_to_important = null; this() { ptr_to_important = new ImportantClass(); } int widget() { if (ptr_to_important == null) ... /* This error-check needs to be included, since you do not know, if function widget() is called from an baseclass-constructor. */ } } These tests to null are stupid, uncomfortable (so nobody will make them), not easy to understand why you need them (I hope you understand it now) and very hard to recognize when you forget them. And they are essentiel. You cannot longer trust the fact like in C++ that never ever a non-static member function is called when constructer- initialisation is not done (exept for those, your own constructor called). Maybe make the calls from within a constructor statically linked is the best solution?Maybe with preinitializing, you can ommit some or most constructors, but you cannot go around the dynamic-linkage-within-constructors-problem.Ok, I understand your point now.This can be done without dynamically linkage within constructors.I *really* wanted to fix that one, having had so many bugs due to it.With D, you have: 1. all members are guaranteed to at least contain their static default values.Wonderful! I missed this one in C++ due lack of sense for typical error situations from the C++-Authority (these are alltogether performance- sharks ;-).values.2. you can use preconditions on a function to guarantee specificSee above. I stated, that this is not the idea of class-invariants. Mixing debugging code and runtime-important code is also one of the great problems with any language I saw (or the fact, that mostly the code will not run at first release build, because somebody wrote "assert(function_with_side_effects()); " ;-)Only in debug! So this is almost useless against unknown source guarantees.You can still leave it on the release code.before3. you can use class invariants to guarantee correct constructionIMHOpublic member functions get called.Also only in debug-mode. Theese are all suits pretty when coding and fast finding errors, butSo you have to mix up debugging and runtime - stuff with the same compiler-identifier? I think the "leave it to the invariant-debug-concept" is not good. Plus, the debugging should stop the code, if something went wrong, and my examples may recover from such a "call before constructor completes".it cannot replace a good scheme of guarantees on runtime!Again, you can leave that stuff turned on.I have seen a C to preprocessor-C converter, which converts plain C code to pure preprocessor-code ;-) (since the preprocessor is turing- compatible).. ImiSoNone of this is supported by C++.hm, somewhat.. you can emulate it, but not use it directly, thats right.D is not more powerful, but much easier to use on those. (But thats not my problem in this thread)<g> All of C++'s features can be emulated in C, after all.
Mar 06 2002
"Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message news:a651sm$voa$1 digitaldaemon.com...Right. You should never forced to use debugging tools for release -things.So all you can do is to add your own "invariant" - code in each function that depend on an correctly, dynamically initialized member.A better idea would be to debug program (using invariants and such) to the state when it surely doesn't depend on uninitialized members. That is, you define an invariant, and develop your program in debug-mode... and then, when you're sure it works properly, you remove all the invariants and let it run at full speed. Or, you could leave the invariants there, even in the release build, to avoid explicitly inserted checks.In my szenario, you have no control over the constructor of B. This is real, because it might be deep in a gui-library (as example MFC).What do you mean, no control???Maybe make the calls from within a constructor statically linked is thebestsolution?I showed how I'd fool the compiler in this case. Anyhow, I think it's not the best idea. I always hated this "feature" of C++, which didn't allow me to define user hooks to be called at the end of the constructor (when all data is surely initialized). This is a very important issue for me, thanks to Walter we have it in D.See above. I stated, that this is not the idea of class-invariants. Mixing debugging code and runtime-important code is also one of the great problems with any language I saw (or the fact, that mostly the code willnotrun at first release build, because somebody wrote "assert(function_with_side_effects()); " ;-)I believe assertions on expressions with side effects are forbidden by the language, and the compiler should do its best to catch such things.
Mar 06 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a659o0$12u2$1 digitaldaemon.com..."Immanuel Scholz" <digitals-mars kutzsche.net> wrote in message news:a651sm$voa$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.Right. You should never forced to use debugging tools for release -things.So all you can do is to add your own "invariant" - code in each function that depend on an correctly, dynamically initialized member.A better idea would be to debug program (using invariants and such) to the state when it surely doesn't depend on uninitialized members. That is, you define an invariant, and develop your program in debug-mode... and then, when you're sure it works properly, you remove all the invariants and let it run at full speed.Or, you could leave the invariants there, even in the release build, to avoid explicitly inserted checks.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.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.In my szenario, you have no control over the constructor of B. This is real, because it might be deep in a gui-library (as example MFC).What do you mean, no control???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.Maybe make the calls from within a constructor statically linked is thebestsolution?I showed how I'd fool the compiler in this case.Anyhow, I think it's not the best idea. I always hated this "feature" of C++, which didn't allow me to define user hooks to be called at the end of the constructor (when all data is surely initialized). This is a very important issue for me, thanks to Walter we have it in D.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).greatSee above. I stated, that this is not the idea of class-invariants. Mixing debugging code and runtime-important code is also one of theI hope he does this job perfect. This is one of the major problems with any #ifdef - related language to me ;-) Imiproblems with any language I saw (or the fact, that mostly the code willnotrun at first release build, because somebody wrote "assert(function_with_side_effects()); " ;-)I believe assertions on expressions with side effects are forbidden by the language, and the compiler should do its best to catch such things.
Mar 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,thatthere 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.
Mar 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...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!)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!calledThis means, "class invariants" degrees to helper-functions that areMaybe 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...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?use.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 toI 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?ifNo, sorry. You cannot fool the compiler to resolve a virtual function,functionsthe vpt of the class is not already build. All calls to virtualfunction?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 virtualI 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.completed.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,thatthere 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 bebecauseif (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,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.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.
Mar 06 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a65sot$1b28$1 digitaldaemon.com...GRRR! Am I talking to a wall? :-|...the wall being asked? =)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.Then, the one who wrote such a library should warn that this function is called before some members are initialized - or, even better, don't do such things at all. Also, if one really needs to call a method of some concrete class, he could specify the full name: class Foo { this() { Foo.bar(); } void bar() { ... } }... 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.This is called "side effects of the constructor" and should be properly documented in the code. That is, it should be stated clearly that CreateWindow is called from the ctor of Window, and once you're aware of it, you can put all the initialization before the call to super(). In fact, it is a wise idea to initialize members before calling super() whenever possible.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?Hmmm... class Foo { int n; this() { ... } } class Bar: Foo { this() { bar(); /* not a base member! */ super(); } void bar() { n = 666; /* modify the base member! */ } } While this example is rather simplistic, I don't see how it can be detected in more general case. Bar.bar() could have been overriden in some descendant of Bar, and you'd never know about it, nor would the compiler...- If you do not call the base class constructor, it is automaticallycalled? Currently, it aborts with an error in such a case, I believe.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."Right way" isn't always the best way. Once again, it depends on the POV.
Mar 06 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a65v6k$1c3n$1 digitaldaemon.com...beYou can NOT (!) always remove the call to the function, because it mayOr we give Walter beer until he make the compiler to warn us. (If possible (both, that Walter build in warnings and that the compiler could warn us)) ;-)essential to the library or you simple CANNOT change the source code, that calls the function.Then, the one who wrote such a library should warn that this function is called before some members are initialized - or, even better, don't do such things at all.switchThe problem here is, that you even might not know, that there are awhen"-with-windows" in Window - class (or the switch is added later one,isn't.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 itThis is called "side effects of the constructor" and should be properly documented in the code. That is, it should be stated clearly that CreateWindow is called from the ctor of Window, and once you're aware of it, you can put all the initialization before the call to super(). In fact, it is a wise idea to initialize members before calling super() whenever possible.I cried out as I read this and was up to shout loudly that the opposite is the truth... But then I realized you were right. (some freely translated phrase of a poem from Goethe ;-) The only thing against it may be, that you need to call base-class functions or you may need base-class members to initialize your class-members. So it may be a good guideline to beginners is to lay out the constructor as follow: this() { /* first do stuff that don't depend on base-class-members or function */ super(); /* now, do stuff that depend on a correct base-class */ } This seems understandable and it should minimize the side effect of surprises... And best: no need to change the compiler ;-)Hm.. If it would not dynamic linked, it could be.... ;-)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?Hmmm... class Foo { int n; this() { ... } } class Bar: Foo { this() { bar(); /* not a base member! */ super(); } void bar() { n = 666; /* modify the base member! */ } } While this example is rather simplistic, I don't see how it can be detected in more general case. Bar.bar() could have been overriden in some descendant of Bar, and you'd never know about it, nor would the compiler...good. Imi- If you do not call the base class constructor, it is automaticallycalled? Currently, it aborts with an error in such a case, I believe.
Mar 06 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a66091$1d3b$1 digitaldaemon.com...So it may be a good guideline to beginners is to lay out the constructor as follow: this() { /* first do stuff that don't depend on base-class-members or function */ super(); /* now, do stuff that depend on a correct base-class */ } This seems understandable and it should minimize the side effect of surprises... And best: no need to change the compiler ;-)Exactly. And BTW that's the way I do it. =)
Mar 06 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a65sot$1b28$1 digitaldaemon.com... <SNIP>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 ! } }Good example.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.In this case you could protect yourself: this () { file = new FileWrapperClass; super(); } I think this works in the general case? Initialize your own fields, call base constructor, do the rest? It looks ugly to me though, I think that the base constructor should be called first normally. -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Mar 06 2002
"OddesE" <OddesE_XYZ hotmail.com> schrieb im Newsbeitrag news:a666h8$1fj1$1 digitaldaemon.com...In this case you could protect yourself: this () { file = new FileWrapperClass; super(); } I think this works in the general case? Initialize your own fields, call base constructor, do the rest? It looks ugly to me though, I think that the base constructor should be called first normally.Yeah. It works for many cases. It does not work for Initializing member functions, that depend on anything that hat to do with the base class, because you would have to access the base before their constructor was through. Maybe it is simple *different* to write classes with such concept. Constructors become more "normal functions" who are implizit called and where you can put some uncritical initialisation in. They loose their academical touch of beeing something you only have to touch with velvet gloves. And maybe this is good so..... ? Because its just pragmatic instead of scietific. Although I do not think it is really good...! ;-) Imi.
Mar 06 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a66ddt$1ioe$1 digitaldaemon.com...concept. Constructors become more "normal functions" who are implizit called and where you can put some uncritical initialisation in. They loose their academical touch of beeing something you only have to touch with velvet gloves. And maybe this is good so..... ? Because its just pragmatic instead of scietific.Yes, yes!!! =)
Mar 06 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a659o0$12u2$1 digitaldaemon.com...I believe assertions on expressions with side effects are forbidden by the language, and the compiler should do its best to catch such things.A probably more accurate statement would be that the assert expression must be written so that its removal or insertion has no effect on the proper operation of the program. Unfortunately, I see no way for the compiler to enforce this beyond trivial cases. Writing good asserts and invariants is a learned skill, and I'm still learning it myself. I do know that the combination of asserts, invariants, and unittests have significantly speeded up my own production of quality code.
Mar 09 2002
"Walter" <walter digitalmars.com> wrote in message news:a6f0t2$2som$1 digitaldaemon.com...A probably more accurate statement would be that the assert expressionmustbe written so that its removal or insertion has no effect on the proper operation of the program. Unfortunately, I see no way for the compiler to enforce this beyond trivial cases.At least it should forbid assignments and function calls there.
Mar 09 2002
"Pavel Minayev" <evilone omen.ru> wrote in message news:a6f11t$2sp1$1 digitaldaemon.com..."Walter" <walter digitalmars.com> wrote in message news:a6f0t2$2som$1 digitaldaemon.com...toA probably more accurate statement would be that the assert expressionmustbe written so that its removal or insertion has no effect on the proper operation of the program. Unfortunately, I see no way for the compilerI have many function calls in my own asserts (like IsEmpty(...), Initialized(), and so on). I suggest you can call only _const_ functions :-) Ciaoenforce this beyond trivial cases.At least it should forbid assignments and function calls there.
Mar 11 2002
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message news:a6ido2$1agt$1 digitaldaemon.com...I suggest you can call only _const_ functions :-)There are no const functions...
Mar 11 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
Mar 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
Mar 06 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a65u2p$1bko$1 digitaldaemon.com...:-[ It seems, that Walter does like printf, or why there are a static printf - member in Object? :-(Static printf() in Object was a bug, AFAIK, and was removed from the class (you can check it in the latest alpha). For now, printf() is the only way to do screen I/O in a more or less convenient way, since we don't have function overloading, typesafe varargs, or variants.Why does Walter do not like warnings?The answer is in the "standartize errors/warnings" thread.
Mar 06 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a65u2p$1bko$1 digitaldaemon.com...Why does Walter do not like warnings?I should put this in the FAQ <g>. The trouble with warnings is they introduce ambiguities into whether a program successfully compiled or not. Many times I've gotten source code from someone, and it compiles with warnings. Are those warnings supposed to be there or not? Who knows? Looking closer at each warning, it turns out to be the result of a problem in the design of the language. They can be eliminated by changing the design. For example, warnings about possible = in conditional: if (a = b) can be eliminated by a language change disallowing assignment in a boolean expression, so the above must be: if ((a = b) != null) or: if (a == b) The need for the warning is gone.
Mar 06 2002
"Walter" <walter digitalmars.com> schrieb im Newsbeitrag news:a671bd$1rjq$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a65u2p$1bko$1 digitaldaemon.com...toWhy does Walter do not like warnings?I should put this in the FAQ <g>. The trouble with warnings is they introduce ambiguities into whether a program successfully compiled or not. Many times I've gotten source code from someone, and it compiles with warnings. Are those warnings supposedbe there or not? Who knows? Looking closer at each warning, it turns out to be the result of a problem in the design of the language. They can be eliminated by changing the design. For example, warnings about possible = in conditional:What about "unused parameter"? If I read right, in D this is an error? But often it is ignored, because you have to declare a parameter (as example because you everride a virtual function) but do not use it: InvisibleLine::draw (int x,int y, int color); Does not need color, because it is invisible, but has to declare a third parameter to be correct overwrite the virtual draw. Imi
Mar 07 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a67p5j$26ie$1 digitaldaemon.com...InvisibleLine::draw (int x,int y, int color); Does not need color, because it is invisible, but has to declare a third parameter to be correct overwrite the virtual draw.The suggested form is: void draw(int x, int y, int /* unnamed */); This makes it clear that the 3rd parameter is not used. I believe that's what Stroustrup said about C++ as well.
Mar 07 2002
"Pavel Minayev" <evilone omen.ru> schrieb im Newsbeitrag news:a681do$2a37$1 digitaldaemon.com..."Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a67p5j$26ie$1 digitaldaemon.com...oh. I thought unnamed parameter were not allowed in D? Great, now I am absolutly satisfied (at least with "no warnings" ;)InvisibleLine::draw (int x,int y, int color); Does not need color, because it is invisible, but has to declare a third parameter to be correct overwrite the virtual draw.The suggested form is: void draw(int x, int y, int /* unnamed */); This makes it clear that the 3rd parameter is not used. I believe that's what Stroustrup said about C++ as well.
Mar 08 2002
"Immanuel Scholz" <digital-mars kutzsche.net> wrote in message news:a6b1b3$14ro$1 digitaldaemon.com...oh. I thought unnamed parameter were not allowed in D?For some reason, they are currently forbidden in function definitions (but allowed in declarations). Following Walter's logic, to prevent the "unused parameter" warning, unnamed parameters must be allowed everywhere...
Mar 08 2002