面向对象的语言有三大特性:继承、封装、多态,虚函数是多态的一种实现方式,另外虚函数的实现又涉及到对象的内存布局,所以这里先说下什么是多态,再说下对象的内存布局,最后说虚函数具体是怎么实现的。
多态
所谓多态指相同的消息给予不同的对象会引发不同的动作。更直接地说,就是“在用父类指针调用函数时,实际调用的是指针指向的实际类型(子类)的成员函数”。多态性使得程序调用的函数是在运行时动态确定的,而不是在编译时静态确定的。
对象的内存布局
简单说下对象的内存布局:成员函数放在代码区,为该类的所有对象公有,即不管新建多少个该类的对象,所对应的都是同一个代码区的函数。而成员变量则为各个对象所私有,即每新建一个对象都会开辟一块内存区用来存储成员变量的值。在调用成员函数时,程序会根据类的类型,找到对应代码区所对应的函数并进行调用。
虚函数的具体实现
虚函数是加了virtual修饰词的类的成员函数。
那么虚函数又是怎么实现的呢?一个类如果有虚函数,这时用sizeof这个类的对象,会多出4个字节,用于存储实现虚函数的关键----虚函数表指针vptr。这个指针指向一张名为“虚函数表”(vtbl)的表,而表中的数据则为函数指针,存储了虚函数具体实现所对应的位置。注意,普通函数、虚函数、虚函数表都是同一个类的所有对象公有的,只有成员变量和虚函数表指针是每个对象私有的,sizeof的值也只包括vptr和成员所占内存的大小,并且vptr通常会在对象内存的最起始位置。另外,当类有多个虚函数时,仍然只有一个虚函数表指针vptr,而此时的虚函数表vtbl中会有多个函数指针,分别指向对应的虚函数实现区域。
总后总结下,虚函数实现的过程:通过对象内存中的vptr找到虚函数表vtbl,接着通过vtbl找到对应虚函数的实现区域并进行调用。
以上就是虚函数的实现方式。