access subclass functions

Christopher Wright dhasenan at gmail.com
Thu Nov 20 20:48:06 PST 2008


Saaa wrote:
>> Informally, "virtual" means "can be overridden". It only applies to
>> methods on classes. This definition is informal and ambiguous.
> virtual functions are slowers because you have the extra step of
> vtable, right?
> How much of a difference can I expect?
> Because it doesn't look like a lot of work: just one single table lookup.

There are two issues, both relating to caching. First, your vtbl might 
not be in cache, which means an expensive memory lookup. Second, the cpu 
  has a cache of instructions you're about to execute; with a 
non-virtual function, that's a fixed target, so the cpu can do better 
prefetching.

In practice, your typeinfo is probably reasonably high in your cache, so 
it won't take very long. A smart compiler should probably put all the 
vtbls in the same region of memory, ideally arranged according to 
inheritance. (Maybe not, I'm not an expert.) Actually arranging this is 
probably quite impossible.

At any rate, if your performance is bad, you'd be better off profiling. 
If profiling doesn't show anything interesting and you still need a 
minor performance boost, you can try marking everything as final. If 
your code consists entirely of function calls, you might get a 20-50% 
speed increase. If it's more typical code, maybe a 2% speed increase. 
(Judging by random microbenchmarks I've seen on the intarwebs.)

>> Virtual dispatch just consists of pointing to a different vtbl with a 
>> different function in that slot.
> Virtual dispatch?

You make a method call. The compiler dispatches that to a particular 
concrete, free-floating function that happens to take a hidden parameter 
named 'this'.

With virtual dispatch, you might call a different function depending on 
the type of 'this'.

> When I need to know whether I can override it, it becomes virtual?
> How does the compiler know that I want that?

If it's final, you can't override it.

If you override something, your override can be final:

class Base
{
    /* virtual */ void foo () { writefln("Base.foo!"); }
}

class Final : Base
{
    // I'm virtual, but you can't override me.
    final override void foo () { writefln("Final.foo!"); }
}

class Fail : Final
{
    // Told you you can't override me.
    override void foo () { writefln("I don't even compile :("); }
}

The rest of what I was saying mainly applies to people using reflection 
to determine whether a function can be overridden.


More information about the Digitalmars-d-learn mailing list