gpt4 book ai didi

c++ - 我明白为什么了,但是 Virtual Functions/VTables 到底是如何允许通过指针访问正确的函数的呢?

转载 作者:行者123 更新时间:2023-11-28 01:23:25 26 4
gpt4 key购买 nike

我在这个网站上找到了一些关于这个主题的优秀线程,多态性的主题对我来说已经很清楚了,但我只是对虚函数与普通函数的工作原理感到困惑。

(此线程中给出的示例 Why do we need virtual functions in C++? ):

class Animal
{
public:
void eat() { std::cout << "I'm eating generic food."<<endl; }
};

class Cat : public Animal
{
public:
void eat() { std::cout << "I'm eating a rat."<<endl; }
};

void func(Animal *xyz) { xyz->eat(); }

所以我们有一个函数和一个被重新定义的派生函数。

Cat *cat = new Cat;
Animal *animal = new Animal;


animal->eat(); // Outputs: "I'm eating generic food."
cat->eat(); // Outputs: "I'm eating a rat."
func(animal); // Outputs: "I'm eating generic food."
func(cat); // Outputs: "I'm eating generic food."

所以如果不是虚函数,我们就无法访问我们想要的函数。但究竟是为什么?

如果以下工作:

Cat cat;
Animal animal;

animal.eat(); // Outputs: "I'm eating generic food."
cat.eat(); // Outputs: "I'm eating a rat."

然后大概内存中已经有两个不同的 eat 函数,不需要 vtable。

因此,当我们将 eat 设为虚函数时,每个类现在都有自己的 vTable 和自己的函数。所以......我们只是将函数存储在内存中的另一个地方。那么指针在通过对象调用常规函数和通过对象调用虚函数之间会发生什么?

至于有什么区别: 动物->吃();//调用虚函数和 动物->吃();//调用常规函数

当我们声明虚函数时,TutorialsPoint 说

This time, the compiler looks at the contents of the pointer instead of it's type

是的,但是怎么做呢?为什么以前不能这样做?它可能只是像常规函数一样存储在内存中。跟对象开头的Vtable指针有关系吗?

我只是在寻找细节以了解原因。我的意思并不是说我陷入了最终毫无意义的事情中。只是出于学术原因想知道。

最佳答案

考虑这段代码:

void Function(Animal *foo)
{
foo->eat();
}

如果 eat 是一个非虚拟成员函数,这只会调用 Animal::eatfoo 指向什么没有区别。

如果 eat 是一个虚拟成员函数,这大致等于 *(foo->eatPtr)(); 。您可以将 Animal 及其所有派生类视为具有指向 eat 函数的成员变量。因此,如果 foo 实际上指向一个 Bear,那么 foo->eatPtr() 将访问 Bear::eatPtr 并调用 eat 类的 Bear 函数。

调用哪个函数是在编译时为非虚函数确定的。所以这将始终调用相同的 eat 函数。对于虚函数,传入的指针用于为 foo 恰好是其成员的特定类查找适当的虚函数表。

这个指向类的 vtable 的额外类成员变量就是为什么类实例或其指针(取决于实现)的大小通常会在添加第一个 virtual 时增加一个指针的大小该类的功能。

关于c++ - 我明白为什么了,但是 Virtual Functions/VTables 到底是如何允许通过指针访问正确的函数的呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55093682/

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