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