Passing a derived class where base class is defined as ref parameter
Mike Parker
aldacron at gmail.com
Tue Dec 14 07:33:53 UTC 2021
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.
More information about the Digitalmars-d-learn
mailing list