首页 > 代码库 > c++特别要点:多态性与虚函数

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(); //非虚函数 静态编译 调用基类的函数}