c++ - 从基类调用函数的多态性
问题描述
所以我有这些课程:
class Base {
public:
Base() {cout << "made a base" << endl;}
virtual void getType() const { cout << "Im a base" << endl;
virtual ~Base() {}
//other members...
}
class Derived: public Base {
public:
Derived() {cout << "made a derived" << endl;
virtual void getType() const { cout << "Im a derived" << endl; }
virtual ~Derived() {}
//other memebrs...
}
int main() {
Base* test = new Derived();
test->getType();
return 0;
}
输出:
made a base
made a derived
Im a derived
现在我知道输出是Im a derived
由于多态性,但是我想知道它如何在内部与 Vftables 一起工作,它如何调用正确的函数,内部的 vtabletest
指向 Base 类getType()
函数,因为test
它的类型知道它是Derived::getType()
而不是Base::getType()
。换句话说,当我的程序看到这个声明时,它在运行时会做什么test->getType()
?
提前致谢。
解决方案
当你这样做Base* test = new Derived()
:
object 的 V-Table 指针test
被设置为指向 class 的 V-Table Derived
。
请注意,当对象被创建时 - 通过new Derived()
- 您显式调用了 class 的函数(构造函数)Derived
而不是 class Base
。
当这个函数被调用时,它会将新对象的 v-table 指针设置为指向 class 的 V-TableDerived
而不是 class 的Base
。
AFAIK,实际的 V 表(两个类的),是由链接器在编译后生成的。
补充:
程序不需要“知道”一个函数是virtual
.
在非虚函数调用的情况下,编译器会在一个常量地址(即非虚函数的地址,在编译过程中可解析)中添加一条JUMP指令。
在虚函数调用的情况下,编译器将 JUMP 指令添加到存储在(指向)变量中的地址,该变量的值仅在运行时解析。
推荐阅读
- mysql - django.db.utils.OperationalError: (1044, "Access denied for user to database) when have permissions
- wordpress - 如何从自定义帖子类型的父类别中获取子类别并显示在下拉列表中?
- sql - Oracle - 函数内带有绑定变量的“错误绑定变量”
- r - 仅根据 R 中句子的一部分查找不同的元素
- javascript - 如何在 swagger-UI 中的 index.html 中设置 url
- azure - 为顶点域创建证书时出现 Azure ARM 模板脚本错误
- android - Android - MutableSharedFlow 无法收集多个订阅者的新值
- ruby-on-rails - 如何使用 Wicked gem 保存用户在向导中停止的步骤?
- openstreetmap - 为什么某些 osmid 属于 OSMNX 中的类型列表?
- java - NPE 同时将图像添加到 JPanel