虚函数的实现原理【虚函数作用】【动态联编】【虚函数表/指针 创建时机、作用、存放位置】
文章目录
0 - 前言
参考:
https://www.nowcoder.com/questionTerminal/1f67d4e2b6134c298e993e622181b333
1 - 虚函数的作用
首先回顾一下动态联编,C++ 多态知识解密【静态联编】【动态联编】【函数重载】【函数重写】【函数重定义】【虚函数表与vptr指针】【纯虚函数】【抽象类】【接口】
-
当父类指针指向对象时,根据对象类型(父类/子类)会调用不同的函数,这一步是在运行时决定的,因此称为动态联编。
-
-
即当父类指针(引用)指向 父类对象时,就调用父类中定义的虚函数;
-
即当父类指针(引用)指向 子类对象时,就调用子类中定义的虚函数;
-
虚函数就是是实现动态联编的关键。将父类中的某个函数以virtual
关键字声明,表明该函数为父类中的虚函数,形式有一般虚函数、纯虚函数两种。不论是哪种形式的虚函数,都能被子类重写,至于子类重写的函数要不要带virtual,就看这个子类是否还会被其他类继承并重写该函数。
//普通虚函数
virtual void print() {
cout << "I'm Parent." << endl;
}
//纯虚函数
virtual void print() = 0;
2 - 虚函数表、虚函数指针
2 - 1 创建时机
-
虚函数表(vtbl, virtual table):编译期间创建,编译器为每个含有虚函数的类创建一个虚函数表
-
虚函数指针(vptr, virtual pointer):运行期间创建,编译器在类构造函数中插入 将虚函数表的地址赋值给虚函数指针 的隐藏代码,因此对象只有运行期间才能获得虚函数指针
2- 2 作用
-
虚函数表:编译器将一个类中的所有虚函数地址存放到虚函数表中。如果该类作为父类被子类继承,子类虚函数表会出现两种情况:
1、
若子类没有重写父类虚函数,则子类虚函数表中存放父类虚函数地址;2、
若子类重写了父类虚函数,则子类虚函数表中存放重写以后的虚函数地址 -
虚函数指针:子类对象有一个/多个(多继承)虚函数指针,指向自己类的虚函数表,vptr的设定(setting)和重置(resetting)都由每一个class的构造函数,析构函数和拷贝赋值运算符自动完成。
2 - 3 存放位置
虚函数表:属于类,类的所有对象共享这个类的虚函数表
虚函数指针:出于效率考虑,会放在每个对象的地址开始处
参考:C++ 虚函数表 存在哪