Inherited constructor
H. S. Teoh
hsteoh at qfbox.info
Fri Jul 25 02:40:35 UTC 2025
On Thu, Jul 24, 2025 at 05:19:17PM +0000, Andy Valencia via Digitalmars-d-learn wrote:
> What is considered the "clean" way to address this error:
>
> ```
> tst60.d(7): Error: class `tst60.B` cannot implicitly generate a
> default constructor when base class `tst60.A` is missing a default
> constructor
> ```
Your base class does not have a default constructor. The only
constructor it has takes a parameter `int val`. This means derived
classes need to invoke `super(...)` and provide an argument for `val`,
since there's no way the compiler can divine what's the correct value to
pass to the base class constructor if you don't specify what it should
be.
If there is a default value that you wish to use when none are
specified, either provide a default constructor that sets `val` to the
default value, or specify a default value.
> Yes, this is a toy example, but it reflects something I'm doing in
> actual code. The subclass has no state, thus it's fine to let the
> superclass take care of initialization. Do I really need a shim like
> this:
>
> ```d
> this(int val) {
> super(val);
> }
> ```
In D, constructors are not inherited, so yes, unfortunately you have to
write a forwarding ctor that passes the arguments along to the base
class. If you find this to be too much boilerplate, there are ways of
using metaprogramming to automate it. I believe code.dlang.org has a
package or two that provides this, or you can write something yourself.
Here's an example of how to do it (caveat: I threw this together in ~5
mins, so there's probably lots of room for improvement):
```
import std;
/**
* Automatically inject ctors that take the same arguments as base class ctors,
* and forwards them to the respective base class ctor.
*/
mixin template ForwardBaseCtors() {
static foreach (Base; BaseClassesTuple!(typeof(this))) {
static foreach (func; MemberFunctionsTuple!(Base, "__ctor")) {
this(Parameters!func args) {
super(args);
}
}
}
}
// Here's your base class
class B {
// Here's a non-default ctor
this(int val, string s, float f) { }
}
// Here's your derived class
class D : B {
// Note: derived class ctor not explicitly specified here
mixin ForwardBaseCtors;
}
void main() {
// Voila! The base class ctor got (semi-)automatically forwarded!
B obj = new D(123, "abc", 3.14159);
}
```
Hope this helps.
T
--
What do you call someone who steals energy from the museum? A Joule thief.
More information about the Digitalmars-d-learn
mailing list