views:

281

answers:

3

I just came to understand Virtual and Override is use for(I can't find a use for so long). Now I'm using them in Factory Patterns. So my question is what does Virtual and Override do behind the scene? I'm willing to go in to IL and Machine code stuff.

+12  A: 

I cannot give you any insights as to how it is done in IL but the basic theory is simple.

When the compiler sees a virtual method declaration, instead of attaching the method to the class, it adds it to what is called a vtable (a Virtual Method Table) for that class, which holds pointers to functions.

Now since the vtable is a part of the class, it is inherited by its subclasses and thus the virtual methods are inherited as well. Now comes the override bit. When the compiler sees an override in a method declaration, it looks up the vtable, finds the method to override and changes the function pointer so that it points to the new definition.

Thus, you get both an inheritance of methods from parent classes and the ability to change their definitions in child classes.

For more information, see the Wikipedia article on the Virtual Method Table.

paracycle
Good explanation!
Chris
Could it be that method in vtable is actually chained rather than overridden ? I'm aiming at fact that from override method we can call overridden method with base.
Petar Repac
I think the chain is implied by inheritance. When you call the base method, you are actually looking up the definition of the virtual method as defined by the base class and calling that one. In effect you lookup the vtable of the base class and use that. That is why you need to call it using base anyway, so that the compiler knows where to look.
paracycle
No, using `base.Foo()` does not involve any further vtable lookup. Why would it - the class always knows its base class, so it knows exactly which method to invoke in a base-call at compile time.
Pavel Minaev
So only if virtual is declared in the base class then the inherited class override won't be called, right? because the complier does not know that the inherited class exists at all at compile time. And the line "When the compiler sees an override in a method declaration" this happen at runtime so how could this happen?
Jonathan Shepherd
Just forget the above second question, I got answer from @harpo
Jonathan Shepherd
@Pavel: Yes you are right, I got confused between compile-time and runtime operations.
paracycle
@Jonathan: If the class `Base` declares a method `int DoIt() { return 5; }` as virtual then when `Base b = new Base(); int a = b.DoIt();` is called, it will call that definition and `a` will be `5`. If a subclass `Sub: Base` overrides the same method as `int DoIt() { return 6; }` and you execute: `Base b1 = new Base(); Base b2 = new Sub(); Sub s = new Sub(); int a1 = b1.DoIt(); int a2 = b2.DoIt(); int a3 = s.DoIt();` you will get `5`, `6` and `6` for `a1`, `a2` and `a3` respectively. Thus each object only calls the definition that is provided by its actual class.
paracycle
@paracycle I completely know how the virtual works. Am just confuse that how does the class get replace at runtime > base class is a; inherit class is b; a test = new b; Without the virtual test.GO() will call the GO() method in a, but my original question is if the "compile-time" does not know about b(because it's assign to a type) how does the virtual version(of this method/function) be able to call b. But anyway I am pretty clear now.
Jonathan Shepherd
Oh sorry, I thought that was what I was trying to explain. Let me quickly try to clear that up. In your example, the compiler knows that the type of the object "test" is "b" even though your are using it as an "a". Thus, in memory, the object is represented with the members/properties from "b" including the "vtable" from "b". When you use it as an "a" you are just seeing a different slice of that memory; however, you are still viewing the same memory addresses, and more importantly, the same "vtable". Thus, a virtual method call resolves to that of "b". There is no magic going on. :)
paracycle
+4  A: 

You don't need to go into the IL - virtual and override encompass a well-known object orientation concept known as polymorphism. Effectively, when a polymorphic method or property is accessed, which method/property actually applies is only determined at runtime. Under the bonnet, basically, the correct method (in the case of a property, it's a method as well) is determined by accessing a virtual method table - a lookup table for finding the right method, based on the runtime type.

Eric Smith
+4  A: 

If you're interested in the IL, use ildasm.exe to look at a compiled program (DLL or EXE). You'll see that the methods you mark as "virtual" are simply marked as "virtual" in the IL.

The magic happens in the runtime. The CLR builds a "method dispatch table" (or "virtual method table"), which it uses to locate your class's methods in memory. In order to allow polymorphism, where the same method name means different things depending on runtime type, some additional lookup is required for virtual methods. (One could say they're called "virtual" methods precisely because they are selected "by virtue" of what they are operating on — but see @Pavel's comments.) Joe Duffy put it this way:

A virtual method call is very much like an ordinary call, except that it must look up the target of the call at runtime based on the 'this' object.

Those are the basics. Don Box is good reading if you really want to go further with this.

harpo
That's an interesting etymology of `virtual`, but I would be curious if this is a retrospective explanation (like VB's `Dim` being explained as `Declare In Memory` by some these days - originally it was from `DIMension`, and only used for arrays), or the real thing; and if the latter, do you have any references? I know that `virtual` in this precise meaning first appeared in the very first OO language, Simula-67. But I don't recall seeing explanation of the keyword in the language reference for that...
Pavel Minaev
Okay, so I'm going out on a limb there... but I feel pretty safe. Declare-in-memory is a new one on me -- I only knew it as the old array-dimensioning keyword. Anyway, glad to hear from a fellow linguaphile.
harpo
Pavel Minaev
Wow, good research. Frankly I find the book rather opaque at the moment, but I think I understand your explanation. It sounds a bit like the way that Dim expanded in its declarative capacity to apply to broader concepts (where "dimensioning" didn't apply). Meanwhile, the virtual function caught on more than the virtual attribute. .NET did not add virtual properties until version 2.0
harpo