反汇编 之 virtual-07 多继承没有覆盖的特点

65 篇文章 1 订阅

#include <iostream>
#include <stdio.h>

/*
 * 多继承没有覆盖的特点
 */

class Base1
{
    public:
        virtual void function_1()
        {
            printf("Base1 function_1...\n");
        }

        virtual void function_2()
        {
            printf("Base1 function_2...\n");
        }
    
};

class Base2
{
    public:
        virtual void function_3()
        {
            printf("Base2 function_3...\n");
        }

        virtual void function_4()
        {
            printf("Base2 function_4...\n");
        }
    
};


class Sub : public Base1, public Base2
{
    public:
        virtual void function_5()
        {
            printf("Sub function_5...\n");
        }

        virtual void function_6()
        {
            printf("Sub function_6...\n");
        }
};

int main(int argc, char ** argv)
{
    Sub sub;

    printf("size = %d\n", sizeof(class Sub));    // 8。 直接继承两个父类,所以有两个虚函数表

    printf("sub address is %x.\n", &sub);        // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。

    /* 对象的前4字节是第一个Base1的虚表 */
    printf("sub virtual table address is:%x\n", *(int*)&sub);           

    typedef void(*pfunction)(void);
    
    pfunction pf;

    for (int i = 0; i < 4; i++) {
        int temp = *((int*)(*(int*)&sub) + i);    
        if (temp == 0) {
            break;
        }

        pf = (pfunction)temp;
        pf();
    }

    /* 对象的第二个4字节是Base2的虚表 */
    printf("sub virtual table address is:%x\n", *(int*)((int)&sub+4));  
    pfunction pf2;

    for (int k = 0; k < 2; k++) {
        int temp = *((int*)(*(int*)((int)&sub+4)) + k);
        pf2 = (pfunction)temp;
        pf2();
    }
}

/*
    sub address is bf989c30.
    sub virtual table address is:8048a48
    Base1 function_1...
    Base1 function_2...
    Sub function_5...
    Sub function_6...
    sub virtual table address is:8048a60
    Base2 function_3...
    Base2 function_4...  
 */

#if 0

1.类多一个直接继承父类,就多一个虚函数表。直接继承一个父类,一个虚函数表;直接继承两个父类,两个虚函数表;
2.间接继承不算。。
3.子类的虚函数放在第一个虚函数表。

sub对象

    ---------------            -----------------
    | 0x123245    |    --------->    Base1 function_1, function_2, Sub function_5, function_6
    ---------------            -----------------
    | 0x123248    |    --------->     Base2 function_3, function_4
    ---------------            
    | ....          |            
    ---------------            
    | ....        |            
    ---------------            
    | ....          |            
    ---------------            
    | 其它成员     |            
    ---------------            
    | ....          |            
    ---------------            

int main(int argc, char ** argv)
{
 80486b0:    55                       push   %ebp
 80486b1:    89 e5                    mov    %esp,%ebp
 80486b3:    83 e4 f0                 and    $0xfffffff0,%esp
 80486b6:    83 ec 30                 sub    $0x30,%esp
    Sub sub;
 80486b9:    8d 44 24 10              lea    0x10(%esp),%eax
 80486bd:    89 04 24                 mov    %eax,(%esp)
 80486c0:    e8 d3 01 00 00           call   8048898 <_ZN3SubC1Ev>

    printf("size = %d\n", sizeof(class Sub));    // 8。 直接继承两个父类,所以有两个虚函数表
 80486c5:    c7 44 24 04 08 00 00     movl   $0x8,0x4(%esp)
 80486cc:    00
 80486cd:    c7 04 24 e0 89 04 08     movl   $0x80489e0,(%esp)
 80486d4:    e8 a7 fe ff ff           call   8048580 <printf@plt>

    printf("sub address is %x.\n", &sub);        // this 指针,是堆栈里面的地址。虚表的地址不是this指针,是this指针的前四个字节。
 80486d9:    8d 44 24 10              lea    0x10(%esp),%eax
 80486dd:    89 44 24 04              mov    %eax,0x4(%esp)
 80486e1:    c7 04 24 eb 89 04 08     movl   $0x80489eb,(%esp)
 80486e8:    e8 93 fe ff ff           call   8048580 <printf@plt>

    /* 对象的前4字节是第一个Base1的虚表 */
    printf("sub virtual table address is:%x\n", *(int*)&sub);           
 80486ed:    8d 44 24 10              lea    0x10(%esp),%eax
 80486f1:    8b 00                    mov    (%eax),%eax
 80486f3:    89 44 24 04              mov    %eax,0x4(%esp)
 80486f7:    c7 04 24 00 8a 04 08     movl   $0x8048a00,(%esp)
 80486fe:    e8 7d fe ff ff           call   8048580 <printf@plt>

    typedef void(*pfunction)(void);
    
    pfunction pf;

    for (int i = 0; i < 4; i++) {
 8048703:    c7 44 24 2c 00 00 00     movl   $0x0,0x2c(%esp)
 804870a:    00
 804870b:    eb 35                    jmp    8048742 <main+0x92>
        int temp = *((int*)(*(int*)&sub) + i);    
 804870d:    8b 44 24 2c              mov    0x2c(%esp),%eax
 8048711:    8d 14 85 00 00 00 00     lea    0x0(,%eax,4),%edx
 8048718:    8d 44 24 10              lea    0x10(%esp),%eax
 804871c:    8b 00                    mov    (%eax),%eax
 804871e:    01 d0                    add    %edx,%eax
 8048720:    8b 00                    mov    (%eax),%eax
 8048722:    89 44 24 24              mov    %eax,0x24(%esp)
        if (temp == 0) {
 8048726:    83 7c 24 24 00           cmpl   $0x0,0x24(%esp)
 804872b:    75 02                    jne    804872f <main+0x7f>
            break;
 804872d:    eb 1a                    jmp    8048749 <main+0x99>
        }

        pf = (pfunction)temp;
 804872f:    8b 44 24 24              mov    0x24(%esp),%eax
 8048733:    89 44 24 20              mov    %eax,0x20(%esp)
        pf();
 8048737:    8b 44 24 20              mov    0x20(%esp),%eax
 804873b:    ff d0                    call   *%eax

    typedef void(*pfunction)(void);
    
    pfunction pf;

    for (int i = 0; i < 4; i++) {
 804873d:    83 44 24 2c 01           addl   $0x1,0x2c(%esp)
 8048742:    83 7c 24 2c 03           cmpl   $0x3,0x2c(%esp)
 8048747:    7e c4                    jle    804870d <main+0x5d>
        pf = (pfunction)temp;
        pf();
    }

    /* 对象的第二个4字节是Base2的虚表 */
    printf("sub virtual table address is:%x\n", *(int*)((int)&sub+4));  
 8048749:    8d 44 24 10              lea    0x10(%esp),%eax
 804874d:    83 c0 04                 add    $0x4,%eax
 8048750:    8b 00                    mov    (%eax),%eax
 8048752:    89 44 24 04              mov    %eax,0x4(%esp)
 8048756:    c7 04 24 00 8a 04 08     movl   $0x8048a00,(%esp)
 804875d:    e8 1e fe ff ff           call   8048580 <printf@plt>
    pfunction pf2;

    for (int k = 0; k < 2; k++) {
 8048762:    c7 44 24 28 00 00 00     movl   $0x0,0x28(%esp)
 8048769:    00
 804876a:    eb 2f                    jmp    804879b <main+0xeb>
        int temp = *((int*)(*(int*)((int)&sub+4)) + k);
 804876c:    8b 44 24 28              mov    0x28(%esp),%eax
 8048770:    8d 14 85 00 00 00 00     lea    0x0(,%eax,4),%edx
 8048777:    8d 44 24 10              lea    0x10(%esp),%eax
 804877b:    83 c0 04                 add    $0x4,%eax
 804877e:    8b 00                    mov    (%eax),%eax
 8048780:    01 d0                    add    %edx,%eax
 8048782:    8b 00                    mov    (%eax),%eax
 8048784:    89 44 24 1c              mov    %eax,0x1c(%esp)
        pf2 = (pfunction)temp;
 8048788:    8b 44 24 1c              mov    0x1c(%esp),%eax
 804878c:    89 44 24 18              mov    %eax,0x18(%esp)
        pf2();
 8048790:    8b 44 24 18              mov    0x18(%esp),%eax
 8048794:    ff d0                    call   *%eax

    /* 对象的第二个4字节是Base2的虚表 */
    printf("sub virtual table address is:%x\n", *(int*)((int)&sub+4));  
    pfunction pf2;

    for (int k = 0; k < 2; k++) {
 8048796:    83 44 24 28 01           addl   $0x1,0x28(%esp)
 804879b:    83 7c 24 28 01           cmpl   $0x1,0x28(%esp)
 80487a0:    7e ca                    jle    804876c <main+0xbc>
        int temp = *((int*)(*(int*)((int)&sub+4)) + k);
        pf2 = (pfunction)temp;
        pf2();
    }
}
 80487a2:    b8 00 00 00 00           mov    $0x0,%eax
 80487a7:    c9                       leave  
 80487a8:    c3                       ret    

#endif

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值