Nis*_*ant 3 c# methods virtual
我理解虚函数是什么.但我没有得到的是他们如何在内部工作?
class Animal
{
virtual string Eat()
{
return @"Eat undefined";
}
}
class Human : Animal
{
override string Eat()
{
return @"Eat like a Human";
}
}
class Dog : Animal
{
new string Eat()
{
return @"Eat like a Dog";
}
}
static void Main()
{
Animal _animal = new Human();
Console.WriteLine(_animal.Eat());
_animal = new Dog();
Console.WriteLine(_animal.Eat());
}
Run Code Online (Sandbox Code Playgroud)
上面的输出给出:
Eat like a Human
Eat undefined
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,_animal是Animal类型,它引用了Human对象或Dog对象.这是什么意思?我理解在内存中_animal包含一个指向Human或Dog对象的地址.它如何决定调用哪个函数.在第一种情况下,我覆盖,因此调用了子的实现,但在第二种情况下,我使用new,因此调用了父实现.能告诉我发动机罩下发生了什么吗?
在此先感谢尼克
Eri*_*ert 17
它的工作原理如下.想象一下,编译器将您的类重写为:
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 } ;
}
}
Run Code Online (Sandbox Code Playgroud)
现在考虑这些电话:
Animal animal;
Dog dog;
animal = new Human();
animal.Eat();
animal = new Animal();
animal.Eat();
dog = new Dog();
dog.Eat();
animal = dog;
animal.Eat();
Run Code Online (Sandbox Code Playgroud)
编译器的原因如下:如果接收器的类型是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
Run Code Online (Sandbox Code Playgroud)
这正是它的工作原理.编译器在后台为您生成vtables,并在编译时决定是否根据重载决策规则调用vtable.
在创建对象时,内存分配器会设置vtable.(我的草图在这方面是谎言,因为vtable是在调用ctor 之前设置的,而不是之后的.)
虚拟方法的"this"实际上是作为方法的不可见形式参数秘密传递的.
合理?