虚函数的实现原理【虚函数作用】【动态联编】【虚函数表/指针 创建时机、作用、存放位置】【vtbl、vptr】

虚函数的实现原理【虚函数作用】【动态联编】【虚函数表/指针 创建时机、作用、存放位置】

0 - 前言

参考:

https://www.nowcoder.com/questionTerminal/1f67d4e2b6134c298e993e622181b333

1 - 虚函数的作用

首先回顾一下动态联编C++ 多态知识解密【静态联编】【动态联编】【函数重载】【函数重写】【函数重定义】【虚函数表与vptr指针】【纯虚函数】【抽象类】【接口】

  • 当父类指针指向对象时,根据对象类型(父类/子类)会调用不同的函数,这一步是在运行时决定的,因此称为动态联编。

    1. 即当父类指针(引用)指向 父类对象时,就调用父类中定义的虚函数;

    2. 即当父类指针(引用)指向 子类对象时,就调用子类中定义的虚函数;

虚函数就是是实现动态联编的关键。将父类中的某个函数以virtual关键字声明,表明该函数为父类中的虚函数,形式有一般虚函数纯虚函数两种。不论是哪种形式的虚函数,都能被子类重写,至于子类重写的函数要不要带virtual,就看这个子类是否还会被其他类继承并重写该函数。

//普通虚函数
virtual void print() {
    
    
    cout << "I'm Parent." << endl;
}
//纯虚函数
virtual void print() = 0;

2 - 虚函数表、虚函数指针

2 - 1 创建时机

  • 虚函数表(vtbl, virtual table):编译期间创建,编译器为每个含有虚函数的类创建一个虚函数表

  • 虚函数指针(vptr, virtual pointer):运行期间创建,编译器在类构造函数中插入 将虚函数表的地址赋值给虚函数指针 的隐藏代码,因此对象只有运行期间才能获得虚函数指针

参考:Cpp 对象模型探索 / 虚函数表和虚函数表指针的创建时机

2- 2 作用

  • 虚函数表:编译器将一个类中的所有虚函数地址存放到虚函数表中。如果该类作为父类被子类继承,子类虚函数表会出现两种情况:1、若子类没有重写父类虚函数,则子类虚函数表中存放父类虚函数地址;2、若子类重写了父类虚函数,则子类虚函数表中存放重写以后的虚函数地址

  • 虚函数指针:子类对象有一个/多个(多继承)虚函数指针,指向自己类的虚函数表,vptr的设定(setting)和重置(resetting)都由每一个class的构造函数,析构函数和拷贝赋值运算符自动完成。

2 - 3 存放位置

虚函数表:属于类,类的所有对象共享这个类的虚函数表

虚函数指针:出于效率考虑,会放在每个对象的地址开始处

参考:C++ 虚函数表 存在哪

猜你喜欢

转载自blog.csdn.net/weixin_44484715/article/details/115067431
今日推荐