虚函数的作用及其底层实现机制

1. C++中虚函数的作用和多态


虚函数: 实现类的多态性

关键字:虚函数;虚函数的作用;多态性;多态公有继承;动态联编

C++中的虚函数的作用主要是实现了多态的机制。基类定义虚函数,子类可以重写该函数;在派生类中对基类定义的虚函数进行重写时,需要再派生类中声明该方法为虚方法。

当子类重新定义了父类的虚函数后,当父类的指针指向子类对象的地址时,[即B b; A a = &b;] 父类指针根据赋给它的不同子类指针,动态的调用子类的该函数,而不是父类的函数(如果不使用virtual方法,请看后面★*),且这样的函数调用发生在运行阶段,而不是发生在编译阶段,称为动态联编。而函数的重载可以认为是多态,只不过是静态的。注意,非虚函数静态联编,效率要比虚函数高,但是不具备动态联编能力。

★如果使用了virtual关键字,程序将根据引用或指针指向的 对 象 类 型 来选择方法,否则使用引用类型或指针类型来选择方法。

下面的例子解释动态联编性:

    class A{
    private:
        int i;
    public:
        A();
        A(int num) :i(num) {};
        virtual void fun1();
        virtual void fun2();

    };

    class B : public A{
    private:
        int j;
    public:
        B(int num) :j(num){};
        virtual void fun2();// 重写了基类的方法
    };

    // 为方便解释思想,省略很多代码

    A a(1);
    B b(2);
    A *a1_ptr = &a;
    A *a2_ptr = &b;

    // 当派生类“重写”了基类的虚方法,调用该方法时
    // 程序根据 指针或引用 指向的  “对象的类型”来选择使用哪个方法
    a1_ptr->fun2();// call A::fun2();
    a2_ptr->fun2();// call B::fun1();
    // 否则
    // 程序根据“指针或引用的类型”来选择使用哪个方法
    a1_ptr->fun1();// call A::fun1();
    a2_ptr->fun1();// call A::fun1();

2. 虚函数的底层实现机制


实现原理:虚函数表+虚表指针

关键字:虚函数底层实现机制;虚函数表;虚表指针

编译器处理虚函数的方法是:为每个类对象添加一个隐藏成员,隐藏成员中保存了一个指向函数地址数组的指针,称为虚表指针(vptr),这种数组成为虚函数表(virtual function table, vtbl),即,每个类使用一个虚函数表,每个类对象用一个虚表指针

举个例子:基类对象包含一个虚表指针,指向基类中所有虚函数的地址表。派生类对象也将包含一个虚表指针,指向派生类虚函数表。看下面两种情况:

  • 如果派生类重写了基类的虚方法,该派生类虚函数表将保存重写的虚函数的地址,而不是基类的虚函数地址。

  • 如果基类中的虚方法没有在派生类中重写,那么派生类将继承基类中的虚方法,而且派生类中虚函数表将保存基类中未被重写的虚函数的地址。注意,如果派生类中定义了新的虚方法,则该虚函数的地址也将被添加到派生类虚函数表中。

下面的图片体现了上述的底层实现机制:

一种虚函数实现机制

  • 21
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值