On Thursday, 24 July 2025 at 17:19:17 UTC, Andy Valencia 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
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:
this(int val) {
super(val);
}
In my class B just to placate the compiler? Is this considered the idiomatic way to deal with such a class organization?
class A {
int v;
this(int val) {
this.v = val;
}
}
class B : A {
int myfunc() {
return this.v;
}
}
int main() {
auto b = new B(1);
return b.myfunc();
}
This is a classic case where A is the "ancestor" class and B is the "heir" class.
If you don't recognize Eiffel language, let's try it in C# or D.
A is the "base" or "parent" class and B is the "derived" or "child" class.
Constructors are not inherited. Each class must provide its own.
When "parent" class has a constructor, derived classes must also have a constructor.
You are welcome to create a do-nothing "child" constructor.
D requires you to "provide the shim" as you indicate.
D requires that a derived class constructor call super(val) somewhere in B's constructor.
It doesn't have to be super(val); It can be super(42); or super(0) or super(val * 10);
The super(...) may be first line, last line, or somewhere in the middle of B's constructor.
B's constructor may do other stuff, but it HAS to include super(...).
D is a bit of a nanny in that it REQUIRES a derived class constructor to call super(val).
There is no way around it if you are using constructors.
If you can't abide by D's fussiness in this matter, there are other OOP languages such as C# and Eiffel that don't require a super(...) call in the derived constructor.
This is an example of D language INSISTING that a derived constructor call its base constructor. This is mostly to keep you out of trouble.
In this case, B's constructor discard A's constructor effects.
FWIW, it is not called a "shim". It is standard programming in D.
Here is working code:
import std.stdio;
class A {
int v;
this(int val) {
this.v = val;
}
}
class B : A {
this(int val) {
super(0); // Have to call super(...)
this.v = val * 10; // Force this.v to ignore whatever super(...) did.
writeln("In B's constructor, calling super(0), then going manual");
}
int myfunc() {
return this.v;
}
}
void main() {
auto b = new B(1);
writeln(b.myfunc());
}
```
A simpler way would be:
import std.stdio;
class A {
int v;
this(int val) {
this.v = val;
}
}
class B : A {
this(int val) {
super(val);
}
int myfunc() {
return this.v;
}
}
void main() {
auto b = new B(1);
writeln(b.myfunc());
}