gpt4 book ai didi

c# - 虚函数 C#

转载 作者:行者123 更新时间:2023-11-30 13:13:40 27 4
gpt4 key购买 nike

我明白什么是虚函数。但我不明白它们在内部是如何工作的?

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());
}

上面的输出给出:

Eat like a Human
Eat undefined

在上面的代码中,_animal 是引用 Human 对象或 Dog 对象的 Animal 类型。这是什么意思?我在内存中了解到 _animal 包含一个指向 Human 或 Dog 对象的地址。它如何决定调用哪个函数。在第一种情况下,我覆盖了,因此调用了子的实现,但在第二种情况下,我使用了 new,因此调用了父的实现。你能解释一下幕后发生了什么吗?

提前致谢尼克

最佳答案

它是这样工作的。想象一下,编译器将您的类重写成这样:

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,那么对 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

正是它的工作原理。编译器在后台为你生成虚表,在编译时根据重载决议的规则决定是否通过虚表调用

vtable 是在创建对象时由内存分配器设置的。 (我的草图在这方面是一个谎言,因为 vtable 是在 调用 ctor 之前设置的,而不是之后设置的。)

虚方法的“this”实际上是作为一个不可见的形参偷偷传递给方法的。

有道理吗?

关于c# - 虚函数 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5307474/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com