当一个子类继承多个父类且重写同名函数时,是怎么实现动态绑定的?

C++代码如下:

#include <iostream>
/**
 * 继承:多继承-3 多个父类继承
 */

#include <iostream>
using namespace std;

class Father1
{

public:
    int a;
    virtual void print()
    {
        a = 1;
    }
};

class Father2
{
public:
    int b;
    virtual void print()
    {
        b = 2;
    }
};

class Father3
{
public:
    int c;
    virtual void print()
    {
        c = 3;
    }
};

class Father4
{
public:
    int d;
    virtual void print()
    {
        d = 4;
    }
};

class Father5
{
public:
    int e;
    virtual void print()
    {
        e = 5;
    }
};

class Son : public Father1, public Father2, public Father3, public Father4, public Father5
{

public:
    int s;
    void print() override
    {
        s = 12;
    }
};

int main()
{
    Son son;
    Father1 &f1 = son;
    f1.print();

    f1.Father1::print();

    Father2 &f2 = son;
    f2.print();

    Father3 &f3 = son;
    f3.print();

    Father4 &f4 = son;
    f4.print();

    Father5 &f5 = son;
    f5.print();
    return 0;
}

汇编代码如下:

    .file    "3-object-class-inherit-6.cpp"
    .text
    .section    .rodata
    .type    _ZStL19piecewise_construct, @object
    .size    _ZStL19piecewise_construct, 1
_ZStL19piecewise_construct:
    .zero    1
    .local    _ZStL8__ioinit
    .comm    _ZStL8__ioinit,1,1
    .section    .text._ZN7Father15printEv,"axG",@progbits,_ZN7Father15printEv,comdat
    .align 2
    .weak    _ZN7Father15printEv
    .type    _ZN7Father15printEv, @function
_ZN7Father15printEv:
.LFB1522:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    $1, 8(%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1522:
    .size    _ZN7Father15printEv, .-_ZN7Father15printEv
    .section    .text._ZN7Father25printEv,"axG",@progbits,_ZN7Father25printEv,comdat
    .align 2
    .weak    _ZN7Father25printEv
    .type    _ZN7Father25printEv, @function
_ZN7Father25printEv:
.LFB1523:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    $2, 8(%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1523:
    .size    _ZN7Father25printEv, .-_ZN7Father25printEv
    .section    .text._ZN7Father35printEv,"axG",@progbits,_ZN7Father35printEv,comdat
    .align 2
    .weak    _ZN7Father35printEv
    .type    _ZN7Father35printEv, @function
_ZN7Father35printEv:
.LFB1524:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    $3, 8(%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1524:
    .size    _ZN7Father35printEv, .-_ZN7Father35printEv
    .section    .text._ZN7Father45printEv,"axG",@progbits,_ZN7Father45printEv,comdat
    .align 2
    .weak    _ZN7Father45printEv
    .type    _ZN7Father45printEv, @function
_ZN7Father45printEv:
.LFB1525:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    $4, 8(%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1525:
    .size    _ZN7Father45printEv, .-_ZN7Father45printEv
    .section    .text._ZN7Father55printEv,"axG",@progbits,_ZN7Father55printEv,comdat
    .align 2
    .weak    _ZN7Father55printEv
    .type    _ZN7Father55printEv, @function
_ZN7Father55printEv:
.LFB1526:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    $5, 8(%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1526:
    .size    _ZN7Father55printEv, .-_ZN7Father55printEv
    .section    .text._ZN3Son5printEv,"axG",@progbits,_ZN3Son5printEv,comdat
    .align 2
    .weak    _ZN3Son5printEv
    .type    _ZN3Son5printEv, @function
_ZN3Son5printEv:
.LFB1527:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    movq    -8(%rbp), %rax
    movl    $12, 76(%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1527:
    .size    _ZN3Son5printEv, .-_ZN3Son5printEv
    .set    .LTHUNK0,_ZN3Son5printEv
    .weak    _ZThn64_N3Son5printEv
    .type    _ZThn64_N3Son5printEv, @function
_ZThn64_N3Son5printEv:
.LFB2029:
    .cfi_startproc
    endbr64
    subq    $64, %rdi
    jmp    .LTHUNK0
    .cfi_endproc
.LFE2029:
    .size    _ZThn64_N3Son5printEv, .-_ZThn64_N3Son5printEv
    .set    .LTHUNK1,_ZN3Son5printEv
    .weak    _ZThn48_N3Son5printEv
    .type    _ZThn48_N3Son5printEv, @function
_ZThn48_N3Son5printEv:
.LFB2030:
    .cfi_startproc
    endbr64
    subq    $48, %rdi
    jmp    .LTHUNK1
    .cfi_endproc
.LFE2030:
    .size    _ZThn48_N3Son5printEv, .-_ZThn48_N3Son5printEv
    .set    .LTHUNK2,_ZN3Son5printEv
    .weak    _ZThn32_N3Son5printEv
    .type    _ZThn32_N3Son5printEv, @function
_ZThn32_N3Son5printEv:
.LFB2031:
    .cfi_startproc
    endbr64
    subq    $32, %rdi
    jmp    .LTHUNK2
    .cfi_endproc
.LFE2031:
    .size    _ZThn32_N3Son5printEv, .-_ZThn32_N3Son5printEv
    .set    .LTHUNK3,_ZN3Son5printEv
    .weak    _ZThn16_N3Son5printEv
    .type    _ZThn16_N3Son5printEv, @function
_ZThn16_N3Son5printEv:
.LFB2032:
    .cfi_startproc
    endbr64
    subq    $16, %rdi
    jmp    .LTHUNK3
    .cfi_endproc
.LFE2032:
    .size    _ZThn16_N3Son5printEv, .-_ZThn16_N3Son5printEv
    .section    .text._ZN7Father1C2Ev,"axG",@progbits,_ZN7Father1C5Ev,comdat
    .align 2
    .weak    _ZN7Father1C2Ev
    .type    _ZN7Father1C2Ev, @function
_ZN7Father1C2Ev:
.LFB1531:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    leaq    16+_ZTV7Father1(%rip), %rdx
    movq    -8(%rbp), %rax
    movq    %rdx, (%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1531:
    .size    _ZN7Father1C2Ev, .-_ZN7Father1C2Ev
    .weak    _ZN7Father1C1Ev
    .set    _ZN7Father1C1Ev,_ZN7Father1C2Ev
    .section    .text._ZN7Father2C2Ev,"axG",@progbits,_ZN7Father2C5Ev,comdat
    .align 2
    .weak    _ZN7Father2C2Ev
    .type    _ZN7Father2C2Ev, @function
_ZN7Father2C2Ev:
.LFB1534:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    leaq    16+_ZTV7Father2(%rip), %rdx
    movq    -8(%rbp), %rax
    movq    %rdx, (%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1534:
    .size    _ZN7Father2C2Ev, .-_ZN7Father2C2Ev
    .weak    _ZN7Father2C1Ev
    .set    _ZN7Father2C1Ev,_ZN7Father2C2Ev
    .section    .text._ZN7Father3C2Ev,"axG",@progbits,_ZN7Father3C5Ev,comdat
    .align 2
    .weak    _ZN7Father3C2Ev
    .type    _ZN7Father3C2Ev, @function
_ZN7Father3C2Ev:
.LFB1537:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    leaq    16+_ZTV7Father3(%rip), %rdx
    movq    -8(%rbp), %rax
    movq    %rdx, (%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1537:
    .size    _ZN7Father3C2Ev, .-_ZN7Father3C2Ev
    .weak    _ZN7Father3C1Ev
    .set    _ZN7Father3C1Ev,_ZN7Father3C2Ev
    .section    .text._ZN7Father4C2Ev,"axG",@progbits,_ZN7Father4C5Ev,comdat
    .align 2
    .weak    _ZN7Father4C2Ev
    .type    _ZN7Father4C2Ev, @function
_ZN7Father4C2Ev:
.LFB1540:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    leaq    16+_ZTV7Father4(%rip), %rdx
    movq    -8(%rbp), %rax
    movq    %rdx, (%rax)
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1540:
    .size    _ZN7Father4C2Ev, .-_ZN7Father4C2Ev
    .weak    _ZN7Father4C1Ev
    .set    _ZN7Father4C1Ev,_ZN7Father4C2Ev
    .section    .text._ZN7Father5C2Ev,"axG",@progbits,_ZN7Father5C5Ev,comdat
    .align 2
    .weak    _ZN7Father5C2Ev
    .type    _ZN7Father5C2Ev, @function
_ZN7Father5C2Ev:
.LFB1543:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movq    %rdi, -8(%rbp)
    leaq    16+_ZTV7Father5(%rip), %rdx # Father5的构造函数地址
    movq    -8(%rbp), %rax
    movq    %rdx, (%rax) # rbp-96+64,Father5的构造函数地址放入Father5对象的首地址处,前8个字节
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1543:
    .size    _ZN7Father5C2Ev, .-_ZN7Father5C2Ev
    .weak    _ZN7Father5C1Ev
    .set    _ZN7Father5C1Ev,_ZN7Father5C2Ev
    .section    .text._ZN3SonC2Ev,"axG",@progbits,_ZN3SonC5Ev,comdat
    .align 2
    .weak    _ZN3SonC2Ev
    .type    _ZN3SonC2Ev, @function
_ZN3SonC2Ev:
.LFB1545:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp

    movq    %rdi, -8(%rbp) # -96(%rbp)
    movq    -8(%rbp), %rax
    movq    %rax, %rdi # -96(%rbp)
    call    _ZN7Father1C2Ev

    movq    -8(%rbp), %rax
    addq    $16, %rax  # rbp-96+16
    movq    %rax, %rdi
    call    _ZN7Father2C2Ev

    movq    -8(%rbp), %rax
    addq    $32, %rax  # rbp-96+32
    movq    %rax, %rdi
    call    _ZN7Father3C2Ev

    movq    -8(%rbp), %rax
    addq    $48, %rax  # rbp-96+48
    movq    %rax, %rdi
    call    _ZN7Father4C2Ev

    movq    -8(%rbp), %rax
    addq    $64, %rax  # rbp-96+64
    movq    %rax, %rdi
    call    _ZN7Father5C2Ev # Father5类的构造函数地址,放入Father5对象的首地址前8个字节处

    leaq    16+_ZTV3Son(%rip), %rdx # _ZN3Son5printEv
    movq    -8(%rbp), %rax # Son类对象首地址、也是Father1对象首地址
    movq    %rdx, (%rax) # 将Son类虚函数表指针,放到Father1类的首地址

    leaq    40+_ZTV3Son(%rip), %rdx # _ZThn16_N3Son5printEv
    movq    -8(%rbp), %rax
    movq    %rdx, 16(%rax) # main函数的rbp-96+16 Father2对象的首地址

    leaq    64+_ZTV3Son(%rip), %rdx # _ZThn32_N3Son5printEv
    movq    -8(%rbp), %rax
    movq    %rdx, 32(%rax) # main函数的rbp-96+32 Father3对象的首地址

    leaq    88+_ZTV3Son(%rip), %rdx # _ZThn48_N3Son5printEv
    movq    -8(%rbp), %rax
    movq    %rdx, 48(%rax) #  main函数的rbp-96+48 Father4对象的首地址

    leaq    112+_ZTV3Son(%rip), %rdx # _ZThn64_N3Son5printEv,调整This指针
    movq    -8(%rbp), %rax
    movq    %rdx, 64(%rax) # main函数的rbp-96+64 Father5对象的首地址
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1545:
    .size    _ZN3SonC2Ev, .-_ZN3SonC2Ev
    .weak    _ZN3SonC1Ev
    .set    _ZN3SonC1Ev,_ZN3SonC2Ev
    .text
    .globl    main
    .type    main, @function
main:
.LFB1528:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $144, %rsp
    movq    %fs:40, %rax
    movq    %rax, -8(%rbp)
    xorl    %eax, %eax

    leaq    -96(%rbp), %rax
    movq    %rax, %rdi
    call    _ZN3SonC1Ev # 在这里面做了下面几件事:
                        #         1. 调用各个父类的构造函数
                        #        2. 将Father1父类对象的前8个字节设置为Son类的虚函数表指针
                        #         3. 将Father2、3、4、5父类对象的前8个字节设置为它们对应的Thunk函数指针

    leaq    -96(%rbp), %rax
    movq    %rax, -136(%rbp)
    movq    -136(%rbp), %rax  # rbp-96
    movq    (%rax), %rax # Son类虚函数表首地址
    movq    (%rax), %rdx # Son类虚函数表的第一个元素的指针,即第一个虚函数
    movq    -136(%rbp), %rax # rbp-96,Son对象首地址
    movq    %rax, %rdi
    call    *%rdx # f1.print();,实际调用的是Son类虚函数表的第一个元素函数,即Son重写的那个print()函数

    movq    -136(%rbp), %rax
    movq    %rax, %rdi
    call    _ZN7Father15printEv # f1.Father1::print();,这就很像调用一个普通函数

    leaq    -96(%rbp), %rax
    addq    $16, %rax
    movq    %rax, -128(%rbp)
    leaq    _ZThn16_N3Son5printEv(%rip), %rdx
    movq    -128(%rbp), %rax
    movq    %rax, %rdi # rbp-96+16
    call    *%rdx # f2.print(); 调用Father2的Thunk指针,rdi传入的是Father2的首地址即rbp-96+16,在Thunk函数里会把指针-16, 修正为Son对象的首地址指针

    leaq    -96(%rbp), %rax
    addq    $32, %rax
    movq    %rax, -120(%rbp)
    leaq    _ZThn32_N3Son5printEv(%rip), %rdx
    movq    -120(%rbp), %rax
    movq    %rax, %rdi # rbp-96+32
    call    *%rdx # f3.print();  同 Father2

    leaq    -96(%rbp), %rax
    addq    $48, %rax
    movq    %rax, -112(%rbp)
    leaq    _ZThn48_N3Son5printEv(%rip), %rdx
    movq    -112(%rbp), %rax
    movq    %rax, %rdi
    call    *%rdx # f4.print();  同 Father2

    leaq    -96(%rbp), %rax
    addq    $64, %rax
    movq    %rax, -104(%rbp)
    leaq    _ZThn64_N3Son5printEv(%rip), %rdx
    movq    -104(%rbp), %rax
    movq    %rax, %rdi
    call    *%rdx # f5.print();  同 Father2

    movl    $0, %eax
    movq    -8(%rbp), %rcx
    xorq    %fs:40, %rcx
    je    .L15
    call    __stack_chk_fail@PLT
.L15:
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1528:
    .size    main, .-main
    .weak    _ZTV3Son
    .section    .data.rel.ro.local._ZTV3Son,"awG",@progbits,_ZTV3Son,comdat
    .align 8
    .type    _ZTV3Son, @object
    .size    _ZTV3Son, 120
_ZTV3Son:
    .quad    0
    .quad    _ZTI3Son
    .quad    _ZN3Son5printEv
    .quad    -16
    .quad    _ZTI3Son
    .quad    _ZThn16_N3Son5printEv
    .quad    -32
    .quad    _ZTI3Son
    .quad    _ZThn32_N3Son5printEv
    .quad    -48
    .quad    _ZTI3Son
    .quad    _ZThn48_N3Son5printEv
    .quad    -64
    .quad    _ZTI3Son
    .quad    _ZThn64_N3Son5printEv
    .weak    _ZTV7Father5
    .section    .data.rel.ro.local._ZTV7Father5,"awG",@progbits,_ZTV7Father5,comdat
    .align 8
    .type    _ZTV7Father5, @object
    .size    _ZTV7Father5, 24
_ZTV7Father5:
    .quad    0
    .quad    _ZTI7Father5
    .quad    _ZN7Father55printEv
    .weak    _ZTV7Father4
    .section    .data.rel.ro.local._ZTV7Father4,"awG",@progbits,_ZTV7Father4,comdat
    .align 8
    .type    _ZTV7Father4, @object
    .size    _ZTV7Father4, 24
_ZTV7Father4:
    .quad    0
    .quad    _ZTI7Father4
    .quad    _ZN7Father45printEv
    .weak    _ZTV7Father3
    .section    .data.rel.ro.local._ZTV7Father3,"awG",@progbits,_ZTV7Father3,comdat
    .align 8
    .type    _ZTV7Father3, @object
    .size    _ZTV7Father3, 24
_ZTV7Father3:
    .quad    0
    .quad    _ZTI7Father3
    .quad    _ZN7Father35printEv
    .weak    _ZTV7Father2
    .section    .data.rel.ro.local._ZTV7Father2,"awG",@progbits,_ZTV7Father2,comdat
    .align 8
    .type    _ZTV7Father2, @object
    .size    _ZTV7Father2, 24
_ZTV7Father2:
    .quad    0
    .quad    _ZTI7Father2
    .quad    _ZN7Father25printEv
    .weak    _ZTV7Father1
    .section    .data.rel.ro.local._ZTV7Father1,"awG",@progbits,_ZTV7Father1,comdat
    .align 8
    .type    _ZTV7Father1, @object
    .size    _ZTV7Father1, 24
_ZTV7Father1:
    .quad    0
    .quad    _ZTI7Father1
    .quad    _ZN7Father15printEv
    .weak    _ZTI3Son
    .section    .data.rel.ro._ZTI3Son,"awG",@progbits,_ZTI3Son,comdat
    .align 8
    .type    _ZTI3Son, @object
    .size    _ZTI3Son, 104
_ZTI3Son:
    .quad    _ZTVN10__cxxabiv121__vmi_class_type_infoE+16
    .quad    _ZTS3Son
    .long    0
    .long    5
    .quad    _ZTI7Father1
    .quad    2
    .quad    _ZTI7Father2
    .quad    4098
    .quad    _ZTI7Father3
    .quad    8194
    .quad    _ZTI7Father4
    .quad    12290
    .quad    _ZTI7Father5
    .quad    16386
    .weak    _ZTS3Son
    .section    .rodata._ZTS3Son,"aG",@progbits,_ZTS3Son,comdat
    .type    _ZTS3Son, @object
    .size    _ZTS3Son, 5
_ZTS3Son:
    .string    "3Son"
    .weak    _ZTI7Father5
    .section    .data.rel.ro._ZTI7Father5,"awG",@progbits,_ZTI7Father5,comdat
    .align 8
    .type    _ZTI7Father5, @object
    .size    _ZTI7Father5, 16
_ZTI7Father5:
    .quad    _ZTVN10__cxxabiv117__class_type_infoE+16
    .quad    _ZTS7Father5
    .weak    _ZTS7Father5
    .section    .rodata._ZTS7Father5,"aG",@progbits,_ZTS7Father5,comdat
    .align 8
    .type    _ZTS7Father5, @object
    .size    _ZTS7Father5, 9
_ZTS7Father5:
    .string    "7Father5"
    .weak    _ZTI7Father4
    .section    .data.rel.ro._ZTI7Father4,"awG",@progbits,_ZTI7Father4,comdat
    .align 8
    .type    _ZTI7Father4, @object
    .size    _ZTI7Father4, 16
_ZTI7Father4:
    .quad    _ZTVN10__cxxabiv117__class_type_infoE+16
    .quad    _ZTS7Father4
    .weak    _ZTS7Father4
    .section    .rodata._ZTS7Father4,"aG",@progbits,_ZTS7Father4,comdat
    .align 8
    .type    _ZTS7Father4, @object
    .size    _ZTS7Father4, 9
_ZTS7Father4:
    .string    "7Father4"
    .weak    _ZTI7Father3
    .section    .data.rel.ro._ZTI7Father3,"awG",@progbits,_ZTI7Father3,comdat
    .align 8
    .type    _ZTI7Father3, @object
    .size    _ZTI7Father3, 16
_ZTI7Father3:
    .quad    _ZTVN10__cxxabiv117__class_type_infoE+16
    .quad    _ZTS7Father3
    .weak    _ZTS7Father3
    .section    .rodata._ZTS7Father3,"aG",@progbits,_ZTS7Father3,comdat
    .align 8
    .type    _ZTS7Father3, @object
    .size    _ZTS7Father3, 9
_ZTS7Father3:
    .string    "7Father3"
    .weak    _ZTI7Father2
    .section    .data.rel.ro._ZTI7Father2,"awG",@progbits,_ZTI7Father2,comdat
    .align 8
    .type    _ZTI7Father2, @object
    .size    _ZTI7Father2, 16
_ZTI7Father2:
    .quad    _ZTVN10__cxxabiv117__class_type_infoE+16
    .quad    _ZTS7Father2
    .weak    _ZTS7Father2
    .section    .rodata._ZTS7Father2,"aG",@progbits,_ZTS7Father2,comdat
    .align 8
    .type    _ZTS7Father2, @object
    .size    _ZTS7Father2, 9
_ZTS7Father2:
    .string    "7Father2"
    .weak    _ZTI7Father1
    .section    .data.rel.ro._ZTI7Father1,"awG",@progbits,_ZTI7Father1,comdat
    .align 8
    .type    _ZTI7Father1, @object
    .size    _ZTI7Father1, 16
_ZTI7Father1:
    .quad    _ZTVN10__cxxabiv117__class_type_infoE+16
    .quad    _ZTS7Father1
    .weak    _ZTS7Father1
    .section    .rodata._ZTS7Father1,"aG",@progbits,_ZTS7Father1,comdat
    .align 8
    .type    _ZTS7Father1, @object
    .size    _ZTS7Father1, 9
_ZTS7Father1:
    .string    "7Father1"
    .text
    .type    _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB2027:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    cmpl    $1, -4(%rbp)
    jne    .L18
    cmpl    $65535, -8(%rbp)
    jne    .L18
    leaq    _ZStL8__ioinit(%rip), %rdi
    call    _ZNSt8ios_base4InitC1Ev@PLT
    leaq    __dso_handle(%rip), %rdx
    leaq    _ZStL8__ioinit(%rip), %rsi
    movq    _ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rax
    movq    %rax, %rdi
    call    __cxa_atexit@PLT
.L18:
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE2027:
    .size    _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
    .type    _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB2028:
    .cfi_startproc
    endbr64
    pushq    %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $65535, %esi
    movl    $1, %edi
    call    _Z41__static_initialization_and_destruction_0ii
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE2028:
    .size    _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
    .section    .init_array,"aw"
    .align 8
    .quad    _GLOBAL__sub_I_main
    .hidden    __dso_handle
    .ident    "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0"
    .section    .note.GNU-stack,"",@progbits
    .section    .note.gnu.property,"a"
    .align 8
    .long     1f - 0f
    .long     4f - 1f
    .long     5
0:
    .string     "GNU"
1:
    .align 8
    .long     0xc0000002
    .long     3f - 2f
2:
    .long     0x3
3:
    .align 8
4:

上述代码主要看main函数的注释就能明白,其实多继承动态绑定的实现原理,本质就是,第1个父类对象的虚函数表地址,直接替换为子类的虚函数表地址,后面所有父类对象的虚函数表地址,全都替换为它们对应的那个Thunk函数的地址,在这个函数里会跳转this指针,本来指向的是父类对象,调整后直接指向了子类对象的虚函数表地址了,这时调用的就是子类对象的虚函数表里面的函数,也就是子类重写的那些函数,这就是多继承下实现【动态绑定】的本质,其实原理很简单。

我的疑问是,【动态绑定】哪里动态了?不还是编译器提前都算好了?哪有堆内存动态分配的样子?那才是真的动态,直接问操作系统要堆内存,具体哪块有内存谁也不知道,每时每刻都不一样,这才是真正的动态啊,不懂。

无语了,为啥发不出去,真难用,决定转到csdn了


大白话的技术分享
4 声望0 粉丝

用最通俗易懂的大白话,总结自己学习的知识,顺带分享技术。