当一个子类继承多个父类且重写同名函数时,是怎么实现动态绑定的?
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了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。