On Monday, 13 December 2021 at 22:06:45 UTC, chopchop wrote:
> If I remove the ref, it works as expected, that is to say I can give a derived class as parameter. I have an idea why it does not work, but I think a c++ reference would work, ie incr(A& console) would accept a B as parameter. What the logic here?
TL:DR it's because there are two levels of indirection.
What's happening here is that ref A
in D is not equivalent to A&
in C++. That's because D classes are reference types like Java classes, not value types like C++ classes. Your b
is a handle to an instance, not an instance itself. It's more akin to B*
in C++. So that means that your ref A
is like A**
in C++. And I believe you'll find that B**
in C++ is not implicitly convertible to A**
.
Since ref
in D is just a pointer under the hood, we can be more explicit like so:
void incr(A* a)
{
writeln(a.i);
}
B b = new B();
incr(&b);
In this case, compilation also fails. B*
is not implicitly convertible to A*
. Again, this is equivalent to B**
and A**
in C++.
In this case, you can explicitly do the conversion with a cast: incr(cast(A*)&b);
But consider what happens in this case:
void incr(A* a)
{
*a = new A;
}
B b = new B();
incr(cast(A*)&b);
writeln(b.j);
Your b
is no longer a B
, but still thinks it is.
This is my understanding of why implicit conversion is disallowed when multiple levels of indirection are involved.