c++中的虚函数及虚函数表

本文探讨了C++中的虚函数及其重要性,解释了虚函数如何允许通过父类指针调用子类的方法。虚函数的实现涉及到虚函数表,每个含有虚函数的类在内存中会有一个指向虚函数表的指针,调用时通过这个表找到正确的函数实现。此外,文章还指出虚函数表存储在代码区,不位于栈或堆中。
摘要由CSDN通过智能技术生成

引语:我们在学习c++中经常会碰到一些莫名其妙的性质,特性等,如虚基类继承,虚函数等,但如果从底层,内存,编译器的角度去理解,那将会发现是如此合理且必要。

c++中,我们来看这一个代码

class A

{

pubilc:

        void  fun()   {  cout<<现调用为A.fun  ;}   

        int   key;
}

class B : publicA                                                   //B由公有继承A,继承了A中的fun()函数

{

        void  fun()   { cout<<现调用为B.fun    ;}         //改写继承来的fun()  
}

在main()中

我们可以定义一个 A * p_a                //一个A类的指针

再来个 B b //定义了一个B 的对象

        并将  p_a=&b    ;        //将b的地址赋给a  注意,指针的类型是A但指向B类

那么如果我们执行这一条语句    p_a->fun()    那么会调用B类里的fun()还是A类里的呢

事实上  将会输出    现调用为A.fun            即调用的是A类里的fun()函数

 为什么要虚函数的存在??

           在实际过程中,我们需要即使指针是一个其父类的指针,但当他指向其子类时,仍调用的是子类的函数或数据     例如,当我们使用析构函数的时候,每个继承来的子类都有自己不同的析构函数,因此应当调用的是子类的析构,而不是父类的析构(即使指针类型为父类的指针)

因此 我们引入虚函数的概念

class A

{

pubilc:

      virtual  void  fun()   {  cout<<现调用为A.fun  ;}      //  将fun()声明为虚函数

        int   key;
}

class B : publicA                                                 

{

        void  fun()   { cout<<现调用为B.fun    ;}         
}

这时候在调用 p_a ->fun   输出     现调用为B.fun        满足我们的要求

虚函数是如何实现的?

       A a;

       B  b;            //声明两个A   B  的对象

       每一个含有虚函数的类被定义时,编译将会创建一个对应的虚函数表

 而A类的对象中    将会包含一个指向虚函数表的指针

所以  当调用虚函数时,是现通过指向虚函数表的指针找到虚函数表,再在虚函数表中通过偏移量找到fun()函数

而当B继承A的时候,也会生成一个属于B的虚函数表,刚开始的时候,虚函数表中的仍是保留A.fun()地址 ,但当我们重写B中的fun()函数时,将会更新为指向我们重新写的地址

由于我们调用虚函数都需要找到虚函数表,因此,通过更新虚函数表中地址,我们可以实现即使是父类的指针,调用的仍然是子类的虚函数。

更进一步 

    那虚函数表是保存在哪个区域,栈区,堆区,代码区?

由于虚函数表需要在类定义开始,到程序结束一直存在,因此不能保留在栈区(栈区调用结束即被回收)。。又因为堆区是我们手动申请的区域,而虚函数表是编译器自动分配的,因此不在堆区

所以虚函数表在代码区   和其他的成员函数在同一个区域。完✿✿ヽ(°▽°)ノ✿

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值