digitalmars.D.learn - Order of base-class constructor calls
- Andrej Mitrovic (42/42) Oct 07 2011 Is there any way to enforce the user to call the base-class ctor via
- Steven Schveighoffer (5/48) Oct 11 2011 Maybe you can make the ctor private? Then the derived class cannot call...
- Andrej Mitrovic (17/17) Oct 11 2011 Nope. Private ctors have to be called from within the same module,
- Steven Schveighoffer (11/28) Oct 12 2011 Hm... that makes sense.
- Regan Heath (32/35) Oct 11 2011 The best I can come up with is a runtime solution:
Is there any way to enforce the user to call the base-class ctor via super(), so it's the first statement in his class ctor? e.g.: class Base { this(int) { } } class Derived : Base { this(int x) { super(x); // user statements } } The problem I'm having is that Base does some required initialization in its ctor, and Derived shouldn't be allowed to call any Base class methods (well, virtual methods) before calling the Base ctor. This is somewhat mitigated if I have a default constructor in the base class, e.g.: class Base { this() { /* init section */ } this(int) { this(); } } class Derived : Base { this(int x) { // Base class ctor automatically called *before* any other statements // user statements.. } } But this is only partially safe as the user could still call super() or super(int) after he's made some calls of his own, e.g.: class Base { this() { /* init section */ } this(int) { this(); } void foo() { /* expects Base.this() having been already called */ } } class Derived : Base { this(int x) { foo(); // boom super(); // or super(int); } } So I'm looking for some techniques or tricks (or, dare I say, design patterns :x) you guys might have if you've ever ran into this kind of problem.
Oct 07 2011
On Fri, 07 Oct 2011 18:02:33 -0400, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Is there any way to enforce the user to call the base-class ctor via super(), so it's the first statement in his class ctor? e.g.: class Base { this(int) { } } class Derived : Base { this(int x) { super(x); // user statements } } The problem I'm having is that Base does some required initialization in its ctor, and Derived shouldn't be allowed to call any Base class methods (well, virtual methods) before calling the Base ctor. This is somewhat mitigated if I have a default constructor in the base class, e.g.: class Base { this() { /* init section */ } this(int) { this(); } } class Derived : Base { this(int x) { // Base class ctor automatically called *before* any other statements // user statements.. } } But this is only partially safe as the user could still call super() or super(int) after he's made some calls of his own, e.g.: class Base { this() { /* init section */ } this(int) { this(); } void foo() { /* expects Base.this() having been already called */ } } class Derived : Base { this(int x) { foo(); // boom super(); // or super(int); } } So I'm looking for some techniques or tricks (or, dare I say, design patterns :x) you guys might have if you've ever ran into this kind of problem.Maybe you can make the ctor private? Then the derived class cannot call it directly, it needs to be implicit. -Steve
Oct 11 2011
Nope. Private ctors have to be called from within the same module, whether implicit or not: test.d: class Foo { private this() { } // Error: constructor main.Bar.this no match for implicit super() call in constructor } import test; class Bar : Foo { this() { } } void main() { auto bar = new Bar(); }
Oct 11 2011
On Tue, 11 Oct 2011 12:40:29 -0400, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:Nope. Private ctors have to be called from within the same module, whether implicit or not: test.d: class Foo { private this() { } // Error: constructor main.Bar.this no match for implicit super() call in constructor } import test; class Bar : Foo { this() { } } void main() { auto bar = new Bar(); }Hm... that makes sense. You can try mucking around with roll-your-own construction. That is, ignore the constructor and use a mixture of public final initialize functions + protected virtual initialize functions. It might just be something that you have to accept is not definable by the base class :( C++ requires construction of base classes before the main body of a derived constructor is called. And that has its own problems too... -Steve
Oct 12 2011
On Fri, 07 Oct 2011 23:02:33 +0100, Andrej Mitrovic <andrej.mitrovich gmail.com> wrote:So I'm looking for some techniques or tricks (or, dare I say, design patterns :x) you guys might have if you've ever ran into this kind of problem.The best I can come up with is a runtime solution: import std.stdio; class Base { private bool _init = false; this(int x) { _init = true; } void foo() { if (_init) writefln("ok"); else writefln("not initialised"); } } class DerivedWell : Base { this(int x) { super(x); foo(); } } class DerivedBadly : Base { this(int x) { foo(); super(x); } } void main() { auto d1 = new DerivedWell(1); auto d2 = new DerivedBadly(1); } -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Oct 11 2011