November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Saaa | Saaa wrote:
>>
>> from the list (private, protected, public) pick public.
>> Note the difference between peel and peal.
> :)
>>
>> public YellowBanana: Banana
>> {
>> void doStuff()
>> {
>> bool e = peel(); //visible from derived
>> //class when defined protected or public.
>> }
>> }
>>
>> Banana a = new Banana();
>> bool f = a.peel(); //visible only when public
>>
>> All non-static non-private non-template member functions are virtual.
>> (Rule only valid in D)
> What does this mean: to be virtual?
Informally, "virtual" means "can be overridden". It only applies to methods on classes. This definition is informal and ambiguous.
According to __traits in d2, "virtual" means "might have a vtbl entry". A vtbl is a list of function pointers corresponding to the methods of a class. Each instance of that class has a pointer to the same list. Virtual dispatch just consists of pointing to a different vtbl with a different function in that slot.
Anyway, the __traits definition maps to the following lemmas[1]:
- static is not virtual
- template is not virtual
- private is not virtual
On the other hand, final functions are virtual. If a final function does not override a virtual function, the compiler can turn it into a free function if that's more efficient. Or maybe not. If a final function overrides a virtual function, it will certainly end up in the class vtbl.
Final functions are a bit questionable. If they override a virtual method in a base class, they should certainly be considered virtual, but you also sometimes need to know whether you can override a function. That is when it's not final and it is virtual.
[1] It's a bit of a stretch to grant them this name, but if life gives you lemmas, make lemma-ade.
|
November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | On Thu, Nov 20, 2008 at 7:35 PM, Christopher Wright <dhasenan@gmail.com> wrote: > [1] It's a bit of a stretch to grant them this name, but if life gives you lemmas, make lemma-ade. > OhhhhhhhhhhhHHHHHHHHHHHHHHHHHHHHHH I think my head just exploded. |
November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | > 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. > > According to __traits in d2, "virtual" means "might have a vtbl entry". A vtbl is a list of function pointers corresponding to the methods of a class. Each instance of that class has a pointer to the same list. Ok > Virtual dispatch just consists of pointing to a different vtbl with a different function in that slot. Virtual dispatch? > Anyway, the __traits definition maps to the following lemmas[1]: - static is not virtual - there is only one function shared with between all the object. > - template is not virtual - I've never used these > - private is not virtual Ok > > On the other hand, final functions are virtual. If a final function does not override a virtual function, the compiler can turn it into a free function if that's more efficient. Or maybe not. If a final function overrides a virtual function, it will certainly end up in the class vtbl. I have never used final either :) > > Final functions are a bit questionable. If they override a virtual method in a base class, they should certainly be considered virtual, but you also sometimes need to know whether you can override a function. That is when it's not final and it is virtual. When I need to know whether I can override it, it becomes virtual? How does the compiler know that I want that? > > > [1] It's a bit of a stretch to grant them this name, but if life gives you lemmas, make lemma-ade. :) |
November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Saaa | 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. |
November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christopher Wright | Thanks !!
I miss university :'(
>>> 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.
|
November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Saaa | Saaa Wrote:
> >> this wrong:
> >> fruits[BANANA].peel();
> >
> > why not using struct?
>
> How do you mean?
> What should be a struct?
>
typed array.
|
November 21, 2008 Re: access subclass functions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kagamin | You mean something like this ?
struct fruits
{
Banana banana();
Apple apple();
}
I now use foreach(int i, Fruit fruit; fruits) a lot.
How do I iterate over all elements when I use the above?
> Saaa Wrote:
>
>> >> this wrong:
>> >> fruits[BANANA].peel();
>> >
>> > why not using struct?
>>
>> How do you mean?
>> What should be a struct?
>>
> typed array.
|
Copyright © 1999-2021 by the D Language Foundation