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:

```d
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:

```d
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.

Reply via email to