C++虚函数

          C++中的虚函数的作用主要是实现了多态的机制。通过虚函数,实现函数调用时的动态绑定,如果调用虚函数,

则直到运行时才能确定调用了哪个函数。

         C++的虚函数通过一张虚函数表来实现,主要是一个类虚函数的地址表,通过这张表,解决了继承、覆盖的问题。

        注意:申请了一个类对象后,占用的地址空间的大小和类的成员函数多少无关,函数都是存放在代码区的,
         不管是全局函数,还是成员函数。(static 函数也是放着代码区,不是放在全局数据区)
 

        C++的编译器暴走虚函数指针存在于对象实例中最前面的位置。所以,我们只要找到存储对象的起始地址,就能找到找到

相关的虚函数表地址,从而能逐个的访问每个虚函数。

        例如定义一个基类:

         class Base{
             int a;
  public:
    virtual void f(){std::cout <<"Base::f()"<<std::endl;}
    virtual void g(){std::cout<<"Base::g()"<<std::endl;}
    void k(){std::cout<<"novirtual function , k()"<<std::endl;}
    virtual void h(){std::cout<<"Base::h()"<<std::endl;}
              };
     我们可以通过下面的代码做一些测试:
            int main()
{
    typedef  void(*Fun)(void);
    Fun fun=NULL;
    Base b;
    cout<<&b<<endl;
    cout<<sizeof(b)<<endl;
    cout<<&b.a<<endl;
    cout<<sizeof(b.a)<<endl;
    return 0;
}

打印结果如下:

        0x28fef4
        8
        0x28fef8

4

分析:(注意sizeof访问的程序的数据段) 通过打印结果,可以看出,b实例分配了8个字节的内存,

相当于两个int的大小,第一个b的一个成员变量a储存在后4个字节空间,前4个字节就是用来存放

虚函数表地址的,因此我们可以通过这个地址来获得虚函数地址。

(int*)(&b) 表示虚函数表地址指针==》*(int*)(&b)虚函数表指针==》 

(int*)*((int *)*(int*)(&b))第一个虚函数地址。下面进行验证:

cout<<(int *)*((int*)*((int *)(&b)))<<endl;
    fun=(Fun)*((int*)*((int *)(&b)));
    fun();

在开始代码后加入上面代码,运行打印结果为:

0x4201e0

Base::f()

根据上面的分析(int*)*((int *)*(int*)(&b)+1)应该是第二个虚函数地址,

(int*)*((int *)*(int*)(&b)+2)应该是第3个虚函数地址。打印可以验证。

fun=(Fun)*((int*)*((int *)(&b))+1);
    fun();

fun=(Fun)*((int*)*((int *)(&b))+2);
    fun();

打印结果为:

Base::g()

Base::h()

如图:


进行继承后:

class Drive:public Base{

public:

   virtual void f1(){std::cout<<"Drive1::f1()"<<std::endl;}

   void g(){std::cout<<"Drive1::g()"<<std::endl;}

    virtual void h1(){std::cout<<"Drive1::h1()"<<std::endl;}

};


在上面继承中 成员函数g()覆盖了Base的虚函数,f1()和h1为继承类新的虚函数,

内存结构如下图:



若为多重继承时,子类中将为每个父类维护一张虚函数表,子类中的成员虚函数被放到第一

个父类的虚函数表中。有覆盖时,将相应表格中相同的虚函数进行覆盖。

  (可以按照最初的方法进行验证)























  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值