它是這樣工作的。試想一下,編譯器改寫了你的類變成這樣:
class VTable
{
public VTable(Func<Animal, string> eat)
{
this.AnimalEat = eat;
}
public readonly Func<Animal, string> AnimalEat;
}
class Animal
{
private static AnimalVTable = new VTable(Animal.AnimalEat);
private static string AnimalEat(Animal _this)
{
return "undefined";
}
public VTable VTable;
public static Animal CreateAnimal()
{
return new Animal()
{ VTable = AnimalVTable };
}
}
class Human : Animal
{
private static HumanVTable = new VTable(Human.HumanEat);
private static string HumanEat(Animal _this)
{
return "human";
}
public static Human CreateHuman()
{
return new Human()
{ VTable = HumanVTable };
}
}
class Dog : Animal
{
public static string DogEat(Dog _this) { return "dog"; }
public static Dog CreateDog()
{
return new Dog()
{ VTable = AnimalVTable } ;
}
}
現在考慮這些調用:
Animal animal;
Dog dog;
animal = new Human();
animal.Eat();
animal = new Animal();
animal.Eat();
dog = new Dog();
dog.Eat();
animal = dog;
animal.Eat();
編譯器的原因如下:如果接收器的類型是動物然後吃一定要到電話animal.VTable.AnimalEat。如果接收器的類型是Dog,則該呼叫必須是DogEat。因此,編譯器寫這些爲:
Animal animal;
Dog dog;
animal = Human.CreateHuman(); // sets the VTable field to HumanVTable
animal.VTable.AnimalEat(animal); // calls HumanVTable.AnimalEat
animal = Animal.CreateAnimal(); // sets the VTable field to AnimalVTable
animal.VTable.AnimalEat(animal); // calls AnimalVTable.AnimalEat
dog = Dog.CreateDog(); // sets the VTable field to AnimalVTable
Dog.DogEat(dog); // calls DogEat, obviously
animal = dog;
animal.VTable.AnimalEat(animal); // calls AnimalVTable.AnimalEat
也就是說正是它是如何工作的。編譯器在後臺爲您生成vtables,並且根據重載分辨率的規則在編譯時決定是否通過vtable調用。
當創建對象時,vtables由內存分配器設置。 (我的素描是這方面的一個謊言,因爲虛函數表設置前的構造函數被調用,而不是之後。)
的「本」的虛方法實際上是祕密爲一種無形的形式參數來傳遞方法。
有意義嗎?
你知道Eric Lippert正在撰寫關於這個主題的博客系列嗎?請參閱http://blogs.msdn.com/b/ericlippert/archive/2011/03/17/implementing-the-virtual-method-pattern-in-c-part-one.aspx – Learner 2011-03-23 08:56:15
謝謝學習者。我正在關注它:) – Nishant 2011-04-05 03:03:14