美文网首页人生几何?
多重继承成员布局与this指针的调整

多重继承成员布局与this指针的调整

作者: 404Not_Found | 来源:发表于2021-09-01 22:54 被阅读0次
  • 作者: 雪山肥鱼
  • 时间:20210901 00:19
  • 目的: 多重继承成员布局与this指针的调整

父类无虚函数,子类有虚函数

class Base
{
public:
    int m_bi;
    Base() {
        printf("Base::Base()的this 指针是 %p\n", this);
    }
};
class Myclass : public Base
{
public:
    int m_i;
    int m_j;
    virtual void myvirfunc()
    {}
    Myclass()
    {
        int abc = 1;
        printf("Myclass::Myclass()的this 指针是 %p\n", this);
    }
    ~Myclass()
    {
        int def = 0;
    }
};

int main(int argc, char **argv)
{
    printf("myclass:m_bi = %d\n", &Myclass::m_bi);
    printf("myclass:m_i = %d\n", &Myclass::m_i);
    printf("myclass:m_j = %d\n", &Myclass::m_j);

    Myclass myobj;
    printf("myobj的地址是:%p\n", &myobj);
    myobj.m_bi = 0;
    myobj.m_i = 1;
    myobj.m_i = 2;

    return 0;
}
this指针位置不同.png

上述布局的输出结果很明显,如下图所示:


布局.png
  • 访问父类的this 与 子类的 this 不同
  • 访问成员变量,this指针都需要进行调整, 才能访问父类的东东。

子类有虚函数,父类也有虚函数

class Base
{
public:
    int m_bi;
    virtual void voidfatherfun()
    {

    }
    Base() {
        printf("Base::Base()的this 指针是 %p\n", this);
    }
};
class Myclass : public Base
{
public:
    int m_i;
    int m_j;
    virtual void myvirfunc()
    {}
    Myclass()
    {
        int abc = 1;
        printf("Myclass::Myclass()的this 指针是 %p\n", this);
    }
    ~Myclass()
    {
        int def = 0;
    }
};

int main(int argc, char **argv)
{
    printf("myclass:m_bi = %d\n", &Myclass::m_bi);
    printf("myclass:m_i = %d\n", &Myclass::m_i);
    printf("myclass:m_j = %d\n", &Myclass::m_j);

    Myclass myobj;
    printf("myobj的地址是:%p\n", &myobj);
    myobj.m_bi = 0;
    myobj.m_i = 1;
    myobj.m_i = 2;

    return 0;
图片.png
  • this 指针相同,父类与子类即使虚函数不同也共用一个vptr
  • 访问父类的东东,this 指针不需要进行调整

多重继承且父类都带虚函数的数据成员布局

class Base1
{
public:
    int m_b1i;
    virtual void voidfatherfun()
    {

    }
    Base1() {
        printf("Base1::Base1()的this 指针是 %p\n", this);
    }
};

class Base2
{
public:
    int m_b2i;
    virtual void voidfatherfun2()
    {

    }
    Base2() {
        printf("Base2::Base2()的this 指针是 %p\n", this);
    }
};
class Myclass : public Base1, public Base2
{
public:
    int m_i;
    int m_j;
    virtual void myvirfunc()
    {}
    Myclass()
    {
        int abc = 1;
        printf("Myclass::Myclass()的this 指针是 %p\n", this);
    }
    ~Myclass()
    {
        int def = 0;
    }
};

int main(int argc, char **argv)
{
    printf("sizeof Myclass:%d\n", sizeof(Myclass));
    printf("myclass:m_bi = %d\n", &Myclass::m_b1i);
    printf("myclass:m_bi = %d\n", &Myclass::m_b2i);
    printf("myclass:m_i = %d\n", &Myclass::m_i);
    printf("myclass:m_j = %d\n", &Myclass::m_j);

    Myclass myobj;
    printf("myobj的地址是:%p\n", &myobj);

    return 0;
}
运行结果.png

B1 和 Myclass 共用一个 this 指针, 如果访问B2 则需要修改this 指针的值。

内存布局如下:


内存布局.png

注意 this 指针的位置是不同的!

结论:
我们要访问一个类对象中的成员,成员定位是通过this指针的来的(编译器会自动调整,比如我们讨论的多重继承中Base1, Base2 就不用) 以及偏移值来定位的。
this指针的调整需要编译器来介入。

深解多重继承中的this偏移

Myclass myobj;
myobj.m_i = 1;
myobj.m_j = 2;
myobj.m_b1i = 3;
myobj.m_b2i = 4;

Base2 * pBase2 = &myobj;

这里的现象很有意思
&myobj 的地址 :
0x00bdfe04 {m_i=1 m_j=2 },
pbase2 的地址:
pbase2 = 0x00bdfe0c

两者并不相同,差了8个字节。
实际编译器是这么操作的:

    Base2 * pbase2 = ( ( (char*)&myobj) + sizeof(Base1) );

这里做的,个人认为是调整了this指针的位置。

同理

Base1 * pbase1 = &myobj 就不会进行调整
    Base2 *pBase3 = new Myclass(); //指向的是 Base2 的 this 指针位置 428
    Myclass *psubobj = (Myclass*)pBase3;// 420

分配堆后,进行转化,发现this 指针 同样调整了8个字节。多继承完全阐述了 编译器堆this指针的调整。

    delete psubobj; // 正确的
    //delete pBase3;// 分配的有问题,说明pBase3 并不是 真个堆的首地址。而是调整了this指针后的地址

下面的 delete pBase3 是绝对有问题的。因为delete不干净。会报错呢。

再次举例:


多重继承的举例.png

学到: 多重继承中,this指针的调整

相关文章

  • c++语法2

    接上篇我们继续学习静态成员、友元函数、继承、多重继承,继承访问权限等 静态成员与友元函数:c++中静态成员与jav...

  • C++多重继承的成员指针问题

    1.cocos2dx开发中遇到一个多继承的问题:ResourceDownloader定义如下: 需要在该类中每帧执...

  • C++

    框架: 构造函数: 继承中的访问控制: 不允许重载的符号: 成员指针与成员函数指针: const的限定: 类中静态...

  • go面向对象-三大特性之继承

    快速入门应用案例 深入讨论 简写 指针的方式 多重继承

  • C++中的多重继承

    多重继承 C++支持编写多重继承的代码一个子类可以拥有多个父类子类拥有所有父类的成员变量子类继承所有父类的成员函数...

  • 慕课网-C++远征之继承篇(下)-学习笔记

    C++远征之继承篇(下) 多继承与多重继承 多重继承: 多继承: 如果不写,那么系统默认为private继承 多重...

  • 2018-12-03

    const 与 多重指针 先让我们来看const与指针的情况 然而,当const碰到多重指针的时候,情况就会变得复...

  • 继承 ---- 重写

    继承: 只有private修饰的成员不能被继承java支持单继承,多重继承(多层次继承),不支持多继承(一个子类有...

  • runtime 中, SEL 和 IMP 的区别

    SEL:类成员方法的指针,方法编号 IMP:函数指针,保存了方法的地址 继承于NSObject的类都被runtim...

  • C语言实现类cpp的类

    基于函数指针实现的成员函数,通过struct嵌套实现简单继承派生和多态。

网友评论

    本文标题:多重继承成员布局与this指针的调整

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