多态性提供接口与具体实现之间的另一层隔离,使创建的程序具有可扩展性。C++支持静态多态和动态多态。
静态多态在编译时期就知道函数的地址,动态多态是指在运行时才确定函数的地址。
动态多态实现的三个条件
- 子类继承父类
- 父类包含虚函数,子类重写虚函数
- 父类指针或引用指向子类对象
对于1,动态多态的意义就是对接口的不同实现。接口是固定的基类,继承基类后,子类便可以重写该接口。
对于2,这就是C++内部实现多态的原理。只要某个类设置了virtual关键字,那么编译器就会分配给该类创建的对象一个虚函数表指针(vptr),这个指针指向该类对应的虚函数表(vtbl,指针数组)。在对象创建时,构造函数会自动给对象一个vptr变量,并赋值为该类vtbl第一个元素的地址。
note:vtbl是对应于类的,所有对象共用一个vtbl;而vptr是对应于类对象的,每个类对象都有一个的vtbl。
对于3,子类会有自己的虚函数指针,指向子类自己的虚函数表。子类若没有重写父类的虚函数,那么虚函数表中的函数指针都和父类的虚函数表的一致;若重写了父类的虚函数,那么就会修改子类虚函数表中对应的函数指针。只要出现引用或指针指向对象,就会触发多态。这是变量的虚函数表就是被指向对象的虚函数表,而不是原来变量自身的虚函数表。
为什么虚函数是运行时才会确定函数地址呢?