c++特别要点:多态性与虚函数
本来是准备在工厂模式中顺便整理。但粗略浏览了,内容还是很多,需要单独开一篇。
一、什么是多态性?
多态性可以概括为“一个接口,多种方法”。
多态与非多态的区别在于“成员函数调用地址的早绑定和晚绑定”。“早绑定”在编译期就可以确定函数的调用地址,是静态的;“晚绑定”在运行时才能确定函数的调用地址,是动态的。
多态的作用是什么呢?在面向对象的编程中,“封装”使得代码模块化;“继承”可以扩展以存在的代码;“多态”使得接口重用。
二、多态性的c++实现:虚函数
声明基类的指针,该指针指向子类的对象。调用相应的虚函数时,可以根据子类的不同而调用不同的函数实现。因此有多态的三个条件:
1)基类指针
2)指向子类对象
3)调用的是虚函数
特殊的,对于强制类型转换,可以将子类对象的指针强制转化为基类对象的指针,
1)当以基类对象的指针调用非虚函数时,仍然调用子类的函数实现
2)当以基类对象的指针调用虚函数时,由于动态绑定,调用的是基类的函数的实现
三、虚函数的底层实现
虚函数(Virtual Function)通过一张虚函数表(Virtual Table)来实现,主是要一个类的虚函数的地址表。在有虚函数的类的实例中保存了指向虚函数表的指针,并且指针存储的位置通常是实例的首地址。
1、虚基类
函数地址在表中的排列顺序同函数的声明顺序。
2、当子类函数覆盖父类虚函数
覆盖的函数f()位于父类虚函数f()的位置,其他函数排列不变。
四、虚函数实例
class base { public: virtual void f() {cout << "in base::f()" << endl;} //虚函数 void g() { cout << "in base::g()" << endl;} //非虚函数 }; class derive: public base { public: virtual void f() {cout << "in derive::f()" << endl;} //覆盖 void g() {cout << "in derive::g()" << endl;} //重载 }; int main(int argc, char **argv) { base *b = new derive(); //基类指针指向派生类的实例 b->f(); //虚函数 动态绑定 调用派生类的函数 b->g(); //非虚函数 静态编译 调用基类的函数 }