美文网首页
我理解的C++虚函数实现机制

我理解的C++虚函数实现机制

作者: 思考着自己的未来 | 来源:发表于2019-10-04 12:27 被阅读0次

虚函数使用方法很简单,直接在函数名前面添加关键字virtual声明即可,如果虚函数末尾增加=0则表示为纯虚函数,纯虚函数要求所有派生类都必须重写该该函数,带有纯虚函数的类我们也称为虚基类。
虚函数的实现,作为一个老生常谈的问题,要想透彻的讲明白,还是需要对底层机制有进一步的理解的。

问题抛出

基类指针为什么能调用子类的虚函数?
虚函数实现的关键原理和虚函数表指针vptr有莫大关系,vptr实际上是指向一个虚函数表(一维数组),该表存储了每个虚函数的函数地址,那么虚函数是如何借助这个vptr实现运行时对象的多态性,也就是我们常说的动态绑定。

从C++对象内存结构说起

阅读过《深度探索C++对象模型》的同学应该比较熟悉下面这个结构,每一个派生类对象实际上是由两个部分组成,如下面的图所示

  • 父类的部分,包括成员变量、vptr、成员函数等,都是共享给子类(当然有一定的权限设置)
  • 子类自身的部分,子类自己成员变量,成员函数

所以子类就是个特殊的父类,享有父类所有属性,是is-a的关系。所以子类也就能直接强制转换为父类,我们通常使用dynamic_cast将子类指针转为父类指针,那么这个父类指针的访问域也就变为内存模型中的上半部分,无法再访问子类的任何资源,但是有个例外,那就是虚表指针vptr,为什么呢?


image-mem.png

我们来进一步看看vptr在类继承过程中到底是怎么变化?
通常函数地址都是在编译的时候就确定了,但是虚函数的调用地址需要到运行的时候才能确定,因为你无法确定一个基类的指针到底是执行基类对象还是子类对象。
实际上,虚函数表指针是在对象执行构造函数的确定的。对于基类来说,执行基类构造函数时,直接把虚函数表填充为基类的虚函数地址即可;对于派生类来说,派生类对象构造的时候,会先执行父类的构造函数(把虚函数表全部填充为基类的虚函数地址),然后再执行子类构造函数(对于子类重写的虚函数,修改虚函数表中对于的函数地址,将其改为子类的虚函数地址),具体过程如下图2个步骤所示:


image-gouzao.png

动态绑定

有了以上基础后,回到之前的问题,动态绑定是怎么发生的?
现在回答这个问题很简单了,对于一个指向子类对象的基类指针,它的vptr其实在子类构造过程被改写过,所以使用基指针调用虚函数的时候,如果子类有重写,会调用子类的虚函数,如果没有重写,则直接调用基类的虚函数,这样就实现了运行时对象的多态性。

代码实例

#include <iostream>
#include <string>
using namespace std;
class Animal
{
public:
    virtual void sleep()
    {
        cout<<"animal sleep"<<endl;
    }
    virtual void breathe()
    {
        cout<<"animal breathe"<<endl;
    }
    string name;
};
class Fish:public Animal
{
public:
    virtual void breathe()
    {
        cout<<"fish bubble"<<endl;
    }
    int skin;
};
int main()
{
    Fish fh;
    Fish *pFish = &fh;
    Animal* pAnimal = dynamic_cast<Animal*>(pFish);
    pAnimal->breathe();//fish bubble 执行子类重写的虚函数
    pAnimal->sleep();  //animal sleep 执行基类的虚函数
    pAnimal->name;     //name位于基类域,能访问
//    pAnimal->skin; skin位于子类域,无法访问
}

相关文章

  • 我理解的C++虚函数实现机制

    虚函数使用方法很简单,直接在函数名前面添加关键字virtual声明即可,如果虚函数末尾增加=0则表示为纯虚函数,纯...

  • 关于objc_runtime的消息机制(二)

    接上篇,我们已经大概的聊完了c++的虚函数实现机制。间接寻址体现在虚函数表的实现上。虚函数表由编译负责帮我们维护。...

  • C++ 虚函数

    C++ 虚函数 虚函数 基类中使用virtual关键字声明的函数,称为虚函数。虚函数的实现,通过虚函数表来实现的。...

  • pwnable.kr之uaf && c++虚函数

    c++的逆向还是要熟悉下。 一、关于c++虚函数 虚函数使得c++能够实现多态,每个类有一个虚表,每个对象在实现的...

  • 虚函数

    简介 虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类的函数。例如下...

  • C++虚函数

    什么是虚函数 C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例...

  • C++中的(纯)虚函数

    简介 本章节会介绍在C++中虚函数及纯虚函数的主要作用,C++也是通过虚函数实现动态绑定,本小节不会去讲述动态绑定...

  • C++面向对象

    小结 虚函数是virtual声明的。实现动态链接的功能。 纯虚函数是没有函数主体的虚函数。 一、C++继承 1.当...

  • C++虚函数

    C++虚函数 C++虚函数是多态性实现的重要方式,当某个虚函数通过指针或者引用调用时,编译器产生的代码直到运行时才...

  • 虚函数、纯虚函数

    1.虚函数(impure virtual) C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类...

网友评论

      本文标题:我理解的C++虚函数实现机制

      本文链接:https://www.haomeiwen.com/subject/bodoyctx.html