zoukankan      html  css  js  c++  java
  • c++虚函数实现与this指针

    我们知道当我们sizeof 一个类的时候,类的成员函数是不计算在对象的大小的里的,这是为什么呢?因为类的成员函数不是属于某一个对象的,而是类的所有对象所共享的,就像static变量那样。如果虚函数和普通成员函数一样,那么我们就不能通过指向子类的基类指针来引用子类的方法了,因为我们将不知道调用哪个方法,多态就无从谈起。那么多态是怎么实现的呢?

    • 虚函数、虚指针与虚表

    我们可以做一个小实验

    class A{
    public:
            int a;
            virtual void myfun(){}
    };
    
    class B:public A{
    public:
            int b;
     };
    B obj_b;
    obj_b.a=1;
    obj_b.b=2; A
    *p=&B; cout<<p<<endl; cout<<&(p->a)<<endl;
    cout<<p->a<<' '<<*(&(p->a)+1)<<endl;

    p的值和&(p->a)的值是相差4个字节的,最后一行输出的值为1 ,2。我们可以推断出obj_b在内存中的分布是首先一个占有4字节的某类型,然后是int a,最后是int b。

    初始的4字节其实就是虚指针。

    而类A的对象在内存的分布其实是虚指针然后是int a。

    如果类B继承A,在B构造的时候,会继承虚指针和int a,但是虚指针指向的虚表就不同了。若在B中实现了虚函数则虚表中的对应函数的入口地址也会改变。从而达到多态的目的。

    注意指针p并访问不到b,因为p是A类型的指针,可见指针的访问范围由的类型决定了。所以我们通过&(p->a)+1来访问b。

    那么多重继承时是什么情况呢?

    多重继承的时候,对于每个有虚函数的基类,子类都会继承相应的虚指针并改写虚表。

    • this指针

    我觉得一篇blog写的挺好就引用过来了。博客地址为:http://www.cnblogs.com/CCQLegend/p/3270738.html

    this指针跟不少人想象的不一样,它的类型由被调用函数决定。它的类型遵循着这两点规则:(途中打勾为首地址。)

    1.对于非虚函数,this指针的基准地址为函数定义所在层级对象的首地址,范围为该层级对象始末。

    如:IA::FF();

    this指针类型是以D0H为首地址,范围是从首地址开始到DFH为止。(其实里面有内存空洞,我们不去纠结这个)

    Derived::FF();

    this指针类型是C0H为首地址,范围是从首地址到E8H为止。

    2.对于虚函数,this指针的基准地址为函数首先声明者的首地址,范围为实现者的始末。

    如:IA::F();

    其this指针类型是以D0H为首地址,范围是从首地址开始到DFH为止。

    Derived::F();

    其this指针类型是以D0H为首地址,范围是从C0H到E8H为止。

    那么当有IA* a=new Derived();后,

    a->F();便是这么访问b成员的了。假设首地址D0H保存在寄存器rax里,

    rax-8

  • 相关阅读:
    php流程控制
    php运算符
    php数据类型
    php基础
    谈谈2019年
    聊聊这三年
    第二次作业(源代码)
    个人介绍
    22.python匿名函数详解
    11.python内置模块之json模块
  • 原文地址:https://www.cnblogs.com/coderht/p/7436860.html
Copyright © 2011-2022 走看看