What are virtual functions?
FeepingCreature
feepingcreature at gmail.com
Wed Apr 14 14:06:18 UTC 2021
On Wednesday, 14 April 2021 at 13:43:20 UTC, Berni44 wrote:
> I'm trying to understand, what virtual functions are. I found
> the
> [specs](https://dlang.org/spec/function.html#virtual-functions), but I can't make head or tail of it.
>
> - What is a `vtbl[]`? Obviously a function pointer table. But
> where to find this? The examples don't use it. Maybe something
> inside of the compiler?
> - Which of the eight functions in the example are virtual and
> and which not? OK B.abc is said to be virtual, as the comment
> states. But it seems never to be used. And why is it considered
> to be virtual?
> - There is also the term "covariant function", which is not
> explained. What is this?
>
Recommended reading:
https://en.wikipedia.org/wiki/Liskov_substitution_principle
This is all related to object-oriented programming and class
inheritance. Because we can put a subclass object into a
superclass variable (`class Child : Parent { }; Parent parent =
new Child;`), we cannot look at the *type* of an object variable
to decide which methods to call, because the object itself may be
of a subtype. As such, when we call a method `foo` on `Parent`,
the compiler looks up the class info in a pointer in the first 8
bytes of the object, finds the method pointer for `foo`, and
calls it with the object as a hidden parameter. (This is the
`this` field.)
So a virtual method is a method that is called "virtually", as
compared to directly by name, by turning the method name into a
function pointer call via the classinfo.
The list of function pointers for methods in the class info is
called the virtual method table, or vtable.
Covariance is related to the Liskov principle, and just means
that because `Child` can be treated as a `Parent`, a method that
returns `Parent` in the superclass can be overridden (its vtable
pointer replaced with a new one) by one that returns a `Child` in
the subclass. In other words, as "Child class replaces Parent
class", the "return type `Child`" can replace the "return type
`Parent`"; ie. in the child class you can use a child class of
the return type, ie. they "vary together" - covariance.
The opposite (contravariance) happens for parameters: if a
superclass method takes `Child`, the subclass can take `Parent`
instead - again, because `Child` can turn into `Parent` per
Liskov.
A different way to think about this is that method parameter and
return types form a contract that is defined by the superclass
and fulfilled by the subclass, and the subclass can relax the
call contract ("I demand from my caller") and restrict the return
contract ("I promise my caller"). Since the `Child`, by Liskov,
can do everything the `Parent` can do, demanding less - ie. a
`Parent` instead of a `Child` - keeps the superclass's call
contract valid, and promising more - ie. returning a `Child`
instead of a `Parent`, which may have additional capabilities -
keeps the superclass's return contract valid.
More information about the Digitalmars-d-learn
mailing list