编译器是如何用汇编语言实现C++的虚函数表和隐式传递this指针(二)

#include <stdio.h>

class Base{
public: 
    Base(){
        puts("Base()");
    }

    virtual void fun1()
    {
        puts("Base::fun1()");
    }

    virtual void fun2()
    {
        puts("Base::fun2()");
    }

    virtual void fun3()
    {
        puts("Base::fun3()");
    }

    void fun4(){
        printf("Normal Base::fun4()\n");
    }

    ~Base(){
        puts("~Base()");
    }
};



class Derive : public Base
{
public: 
    Derive()
    {
        puts("Derive()");
    }

    void fun1()
    {
        puts("Derive::fun1()");
    }

    void fun2()
    {
        puts("Derive::fun2()");
    }

/*    void fun3()
    {
        puts("Derive::fun3()");
    }

  */  

    void fun4(){
        printf("Normal Derive::fun4()\n");
    }

    ~Derive(){
        puts("~Derive()");
    }
};

typedef void (*FUN) (void);

int main()
{
    FUN pfun1 = NULL;
    FUN pfun2 = NULL;
    FUN pfun3 = NULL;

    Derive b;
    printf("&b = %p\n",(&b));
    printf("vtable = %p\n",(int *)(&b));
    printf("*vtable = %p\n",**(int **)(&b));//取vtable第一个函数的地址
    printf("b = %p\n",*(int*)(&b));

    pfun1 = (FUN)**(int**)(&b);
    printf("fun1 = %p\n",pfun1);
    pfun1();
    pfun2 = (FUN)*(*(int**)(&b)+1);
    printf("fun2 = %p\n",pfun2);
    pfun2();
    //b.fun2();
    pfun3 = (FUN)*(*(int**)(&b)+2);
    printf("fun3 = %p\n",pfun3);
    pfun3();
    b.fun4();

    Base * pb = &b;
    pb->fun2();
    pb->fun3();
    pb->fun4();
    return 0;
}

/* 输出结果如下
Base()
Derive()
&b = 0xbfe919dc
vtable = 0xbfe919dc
*vtable = 0x80487ca
b = 0x80489e8
fun1 = 0x80487ca
Derive::fun1()
fun2 = 0x80487de
Derive::fun2()
fun3 = 0x804874c
Base::fun3()
Normal Derive::fun4()
Derive::fun2()
Base::fun3()
Normal Base::fun4()
~Derive()
~Base()
*/

//看一下汇编代码是如何实现的

/*	
	.file	"vtable.cpp"
	.section	.rodata
.LC0:
	.string	"Base()"
	.section	.text._ZN4BaseC2Ev,"axG",@progbits,_ZN4BaseC2Ev,comdat
	.align 2
	.weak	_ZN4BaseC2Ev
	.type	_ZN4BaseC2Ev, @function
_ZN4BaseC2Ev:  #Base的构造函数
.LFB1:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	8(%ebp), %eax
	movl	$_ZTV4Base+8, (%eax) #Base的vtable赋值给对象的前4个字节的地址空间
	movl	$.LC0, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE1:
	.size	_ZN4BaseC2Ev, .-_ZN4BaseC2Ev
	.section	.rodata
.LC1:
	.string	"Base::fun1()"
	.section	.text._ZN4Base4fun1Ev,"axG",@progbits,_ZN4Base4fun1Ev,comdat
	.align 2
	.weak	_ZN4Base4fun1Ev
	.type	_ZN4Base4fun1Ev, @function
_ZN4Base4fun1Ev:
.LFB3:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC1, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE3:
	.size	_ZN4Base4fun1Ev, .-_ZN4Base4fun1Ev
	.section	.rodata
.LC2:
	.string	"Base::fun2()"
	.section	.text._ZN4Base4fun2Ev,"axG",@progbits,_ZN4Base4fun2Ev,comdat
	.align 2
	.weak	_ZN4Base4fun2Ev
	.type	_ZN4Base4fun2Ev, @function
_ZN4Base4fun2Ev:
.LFB4:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC2, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE4:
	.size	_ZN4Base4fun2Ev, .-_ZN4Base4fun2Ev
	.section	.rodata
.LC3:
	.string	"Base::fun3()"
	.section	.text._ZN4Base4fun3Ev,"axG",@progbits,_ZN4Base4fun3Ev,comdat
	.align 2
	.weak	_ZN4Base4fun3Ev
	.type	_ZN4Base4fun3Ev, @function
_ZN4Base4fun3Ev:
.LFB5:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC3, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE5:
	.size	_ZN4Base4fun3Ev, .-_ZN4Base4fun3Ev
	.section	.rodata
.LC4:
	.string	"Normal Base::fun4()"
	.section	.text._ZN4Base4fun4Ev,"axG",@progbits,_ZN4Base4fun4Ev,comdat
	.align 2
	.weak	_ZN4Base4fun4Ev
	.type	_ZN4Base4fun4Ev, @function
_ZN4Base4fun4Ev:
.LFB6:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC4, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE6:
	.size	_ZN4Base4fun4Ev, .-_ZN4Base4fun4Ev
	.section	.rodata
.LC5:
	.string	"~Base()"
	.section	.text._ZN4BaseD2Ev,"axG",@progbits,_ZN4BaseD2Ev,comdat
	.align 2
	.weak	_ZN4BaseD2Ev
	.type	_ZN4BaseD2Ev, @function
_ZN4BaseD2Ev:
.LFB8:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	8(%ebp), %eax
	movl	$_ZTV4Base+8, (%eax)
	movl	$.LC5, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE8:
	.size	_ZN4BaseD2Ev, .-_ZN4BaseD2Ev
	.section	.rodata
.LC6:
	.string	"Derive()"
.globl _Unwind_Resume
	.section	.text._ZN6DeriveC1Ev,"axG",@progbits,_ZN6DeriveC1Ev,comdat
	.align 2
	.weak	_ZN6DeriveC1Ev
	.type	_ZN6DeriveC1Ev, @function
_ZN6DeriveC1Ev: #Derive的构造函数
.LFB12:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	.cfi_lsda 0x0,.LLSDA12
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	pushl	%esi
	pushl	%ebx
	subl	$16, %esp
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
.LEHB0:
	.cfi_offset 3, -16
	.cfi_offset 6, -12
	call	_ZN4BaseC2Ev #先调用基类Base的构造函数 得到基类的vtable
.LEHE0:
	movl	8(%ebp), %eax
	movl	$_ZTV6Derive+8, (%eax)  #用子类的vtable覆盖
	movl	$.LC6, (%esp)
.LEHB1:
	call	puts
.LEHE1:
	jmp	.L18
.L17:
.L15:
	movl	%edx, %ebx
	movl	%eax, %esi
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_ZN4BaseD2Ev
	movl	%esi, %eax
	movl	%ebx, %edx
	movl	%eax, (%esp)
.LEHB2:
	call	_Unwind_Resume
.LEHE2:
.L18:
	addl	$16, %esp
	popl	%ebx
	.cfi_restore 3
	popl	%esi
	.cfi_restore 6
	popl	%ebp
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE12:
	.size	_ZN6DeriveC1Ev, .-_ZN6DeriveC1Ev
.globl __gxx_personality_v0
	.section	.gcc_except_table,"a",@progbits
.LLSDA12:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 .LLSDACSE12-.LLSDACSB12
.LLSDACSB12:
	.uleb128 .LEHB0-.LFB12
	.uleb128 .LEHE0-.LEHB0
	.uleb128 0x0
	.uleb128 0x0
	.uleb128 .LEHB1-.LFB12
	.uleb128 .LEHE1-.LEHB1
	.uleb128 .L17-.LFB12
	.uleb128 0x0
	.uleb128 .LEHB2-.LFB12
	.uleb128 .LEHE2-.LEHB2
	.uleb128 0x0
	.uleb128 0x0
.LLSDACSE12:
	.section	.text._ZN6DeriveC1Ev,"axG",@progbits,_ZN6DeriveC1Ev,comdat
	.section	.rodata
.LC7:
	.string	"Derive::fun1()"
	.section	.text._ZN6Derive4fun1Ev,"axG",@progbits,_ZN6Derive4fun1Ev,comdat
	.align 2
	.weak	_ZN6Derive4fun1Ev
	.type	_ZN6Derive4fun1Ev, @function
_ZN6Derive4fun1Ev:
.LFB13:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC7, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE13:
	.size	_ZN6Derive4fun1Ev, .-_ZN6Derive4fun1Ev
	.section	.rodata
.LC8:
	.string	"Derive::fun2()"
	.section	.text._ZN6Derive4fun2Ev,"axG",@progbits,_ZN6Derive4fun2Ev,comdat
	.align 2
	.weak	_ZN6Derive4fun2Ev
	.type	_ZN6Derive4fun2Ev, @function
_ZN6Derive4fun2Ev:
.LFB14:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC8, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE14:
	.size	_ZN6Derive4fun2Ev, .-_ZN6Derive4fun2Ev
	.section	.rodata
.LC9:
	.string	"Normal Derive::fun4()"
	.section	.text._ZN6Derive4fun4Ev,"axG",@progbits,_ZN6Derive4fun4Ev,comdat
	.align 2
	.weak	_ZN6Derive4fun4Ev
	.type	_ZN6Derive4fun4Ev, @function
_ZN6Derive4fun4Ev:
.LFB15:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	$.LC9, (%esp)
	call	puts
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE15:
	.size	_ZN6Derive4fun4Ev, .-_ZN6Derive4fun4Ev
	.section	.rodata
.LC10:
	.string	"~Derive()"
	.section	.text._ZN6DeriveD1Ev,"axG",@progbits,_ZN6DeriveD1Ev,comdat
	.align 2
	.weak	_ZN6DeriveD1Ev
	.type	_ZN6DeriveD1Ev, @function
_ZN6DeriveD1Ev:
.LFB18:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	.cfi_lsda 0x0,.LLSDA18
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	pushl	%esi
	pushl	%ebx
	subl	$16, %esp
	movl	8(%ebp), %eax
	movl	$_ZTV6Derive+8, (%eax)
	movl	$.LC10, (%esp)
.LEHB3:
	.cfi_offset 3, -16
	.cfi_offset 6, -12
	call	puts
.LEHE3:
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
.LEHB4:
	call	_ZN4BaseD2Ev
.LEHE4:
	addl	$16, %esp
	popl	%ebx
	.cfi_remember_state
	.cfi_restore 3
	popl	%esi
	.cfi_restore 6
	popl	%ebp
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
.L29:
	.cfi_restore_state
.L27:
	movl	%edx, %ebx
	movl	%eax, %esi
	movl	8(%ebp), %eax
	movl	%eax, (%esp)
	call	_ZN4BaseD2Ev
	movl	%esi, %eax
	movl	%ebx, %edx
	movl	%eax, (%esp)
.LEHB5:
	call	_Unwind_Resume
.LEHE5:
	.cfi_endproc
.LFE18:
	.size	_ZN6DeriveD1Ev, .-_ZN6DeriveD1Ev
	.section	.gcc_except_table
.LLSDA18:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 .LLSDACSE18-.LLSDACSB18
.LLSDACSB18:
	.uleb128 .LEHB3-.LFB18
	.uleb128 .LEHE3-.LEHB3
	.uleb128 .L29-.LFB18
	.uleb128 0x0
	.uleb128 .LEHB4-.LFB18
	.uleb128 .LEHE4-.LEHB4
	.uleb128 0x0
	.uleb128 0x0
	.uleb128 .LEHB5-.LFB18
	.uleb128 .LEHE5-.LEHB5
	.uleb128 0x0
	.uleb128 0x0
.LLSDACSE18:
	.section	.text._ZN6DeriveD1Ev,"axG",@progbits,_ZN6DeriveD1Ev,comdat
	.section	.rodata
.LC11:
	.string	"&b = %p\n"
.LC12:
	.string	"vtable = %p\n"
.LC13:
	.string	"*vtable = %p\n"
.LC14:
	.string	"b = %p\n"
.LC15:
	.string	"fun1 = %p\n"
.LC16:
	.string	"fun2 = %p\n"
.LC17:
	.string	"fun3 = %p\n"
	.text
.globl main
	.type	main, @function
main:
.LFB19:
	.cfi_startproc
	.cfi_personality 0x0,__gxx_personality_v0
	.cfi_lsda 0x0,.LLSDA19
	pushl	%ebp
	.cfi_def_cfa_offset 8
	movl	%esp, %ebp
	.cfi_offset 5, -8
	.cfi_def_cfa_register 5
	andl	$-16, %esp
	pushl	%esi
	pushl	%ebx
	subl	$56, %esp
	movl	$0, 32(%esp)
	movl	$0, 36(%esp)
	movl	$0, 40(%esp)
	leal	28(%esp), %eax
	movl	%eax, (%esp)
.LEHB6:
	.cfi_escape 0x10,0x3,0x8,0x75,0x0,0x9,0xf0,0x1a,0x9,0xf8,0x22
	.cfi_escape 0x10,0x6,0x8,0x75,0x0,0x9,0xf0,0x1a,0x9,0xfc,0x22
	call	_ZN6DeriveC1Ev #调用构造函数
.LEHE6:
	leal	28(%esp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC11, (%esp)
.LEHB7:
	call	printf    #printf("&b = %p\n",(&b));
	leal	28(%esp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC12, (%esp)
	call	printf	#printf("vtable = %p\n",(int *)(&b));
	leal	28(%esp), %eax
	movl	(%eax), %eax
	movl	(%eax), %eax
	movl	%eax, 4(%esp)
	movl	$.LC13, (%esp)
	call	printf	#printf("*vtable = %p\n",**(int **)(&b));
	leal	28(%esp), %eax
	movl	(%eax), %eax
	movl	%eax, 4(%esp)
	movl	$.LC14, (%esp)
	call	printf    #printf("b = %p\n",*(int*)(&b));
	leal	28(%esp), %eax
	movl	(%eax), %eax
	movl	(%eax), %eax
	movl	%eax, 32(%esp)
	movl	32(%esp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC15, (%esp)
	call	printf    #printf("fun1 = %p\n",pfun1);
	movl	32(%esp), %eax
	call	*%eax     #    pfun1(); 
	leal	28(%esp), %eax
	movl	(%eax), %eax
	addl	$4, %eax
	movl	(%eax), %eax
	movl	%eax, 36(%esp)
	movl	36(%esp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC16, (%esp)
	call	printf   #printf("fun2 = %p\n",pfun2);
	movl	36(%esp), %eax
	call	*%eax     #pfun2();
	leal	28(%esp), %eax
	movl	(%eax), %eax
	addl	$8, %eax
	movl	(%eax), %eax
	movl	%eax, 40(%esp)
	movl	40(%esp), %eax
	movl	%eax, 4(%esp)
	movl	$.LC17, (%esp)
	call	printf   # printf("fun3 = %p\n",pfun3);
	movl	40(%esp), %eax
	call	*%eax     #pfun3();
	leal	28(%esp), %eax
	movl	%eax, (%esp)
	call	_ZN6Derive4fun4Ev   # b.fun4();
	leal	28(%esp), %eax      #基类指针指向子类对象
	movl	%eax, 44(%esp)
	movl	44(%esp), %eax
	movl	(%eax), %eax        #经过一系列变幻得到*vtable
	addl	$4, %eax            #加4 得到_ZN6Derive4fun2Ev 即fun2。虽然都是fun2 基类是_ZN4Base4fun2Ev 与子类是不同的
	movl	(%eax), %edx
	movl	44(%esp), %eax
	movl	%eax, (%esp)
	call	*%edx     #pb->fun2();
	movl	44(%esp), %eax
	movl	(%eax), %eax
	addl	$8, %eax            #加8_ZN4Base4fun3Ev,因为子类没有重写所以这是基类Base的函数原型
	movl	(%eax), %edx
	movl	44(%esp), %eax
	movl	%eax, (%esp)
	call	*%edx    #pb->fun3();
	movl	44(%esp), %eax
	movl	%eax, (%esp)
	call	_ZN4Base4fun4Ev #  pb->fun4();;
.LEHE7:
	movl	$0, %ebx
	leal	28(%esp), %eax
	movl	%eax, (%esp)
.LEHB8:
	call	_ZN6DeriveD1Ev
.LEHE8:
	movl	%ebx, %eax
	addl	$56, %esp
	popl	%ebx
	.cfi_remember_state
	.cfi_restore 3
	popl	%esi
	.cfi_restore 6
	movl	%ebp, %esp
	.cfi_def_cfa_register 4
	popl	%ebp
	.cfi_restore 5
	.cfi_def_cfa_offset 4
	ret
.L33:
	.cfi_restore_state
.L31:
	movl	%edx, %ebx
	movl	%eax, %esi
	leal	28(%esp), %eax
	movl	%eax, (%esp)
	call	_ZN6DeriveD1Ev
	movl	%esi, %eax
	movl	%ebx, %edx
	movl	%eax, (%esp)
.LEHB9:
	call	_Unwind_Resume
.LEHE9:
	.cfi_endproc
.LFE19:
	.size	main, .-main
	.section	.gcc_except_table
.LLSDA19:
	.byte	0xff
	.byte	0xff
	.byte	0x1
	.uleb128 .LLSDACSE19-.LLSDACSB19
.LLSDACSB19:
	.uleb128 .LEHB6-.LFB19
	.uleb128 .LEHE6-.LEHB6
	.uleb128 0x0
	.uleb128 0x0
	.uleb128 .LEHB7-.LFB19
	.uleb128 .LEHE7-.LEHB7
	.uleb128 .L33-.LFB19
	.uleb128 0x0
	.uleb128 .LEHB8-.LFB19
	.uleb128 .LEHE8-.LEHB8
	.uleb128 0x0
	.uleb128 0x0
	.uleb128 .LEHB9-.LFB19
	.uleb128 .LEHE9-.LEHB9
	.uleb128 0x0
	.uleb128 0x0
.LLSDACSE19:
	.text
	.weak	_ZTV6Derive
	.section	.rodata._ZTV6Derive,"aG",@progbits,_ZTV6Derive,comdat
	.align 8
	.type	_ZTV6Derive, @object
	.size	_ZTV6Derive, 20
_ZTV6Derive:
	.long	0
	.long	_ZTI6Derive
	.long	_ZN6Derive4fun1Ev        #Derive vtable
	.long	_ZN6Derive4fun2Ev
	.long	_ZN4Base4fun3Ev
	.weak	_ZTV4Base
	.section	.rodata._ZTV4Base,"aG",@progbits,_ZTV4Base,comdat
	.align 8
	.type	_ZTV4Base, @object
	.size	_ZTV4Base, 20
_ZTV4Base:
	.long	0
	.long	_ZTI4Base      
	.long	_ZN4Base4fun1Ev         #Base vtable
	.long	_ZN4Base4fun2Ev
	.long	_ZN4Base4fun3Ev
	.weak	_ZTS6Derive
	.section	.rodata._ZTS6Derive,"aG",@progbits,_ZTS6Derive,comdat
	.type	_ZTS6Derive, @object
	.size	_ZTS6Derive, 8
_ZTS6Derive:
	.string	"6Derive"
	.weak	_ZTI6Derive
	.section	.rodata._ZTI6Derive,"aG",@progbits,_ZTI6Derive,comdat
	.align 4
	.type	_ZTI6Derive, @object
	.size	_ZTI6Derive, 12
_ZTI6Derive:
	.long	_ZTVN10__cxxabiv120__si_class_type_infoE+8
	.long	_ZTS6Derive
	.long	_ZTI4Base
	.weak	_ZTS4Base
	.section	.rodata._ZTS4Base,"aG",@progbits,_ZTS4Base,comdat
	.type	_ZTS4Base, @object
	.size	_ZTS4Base, 6
_ZTS4Base:
	.string	"4Base"
	.weak	_ZTI4Base
	.section	.rodata._ZTI4Base,"aG",@progbits,_ZTI4Base,comdat
	.align 4
	.type	_ZTI4Base, @object
	.size	_ZTI4Base, 8
_ZTI4Base:
	.long	_ZTVN10__cxxabiv117__class_type_infoE+8
	.long	_ZTS4Base
	.ident	"GCC: (GNU) 4.4.2 20091027 (Red Hat 4.4.2-7)"
	.section	.note.GNU-stack,"",@progbits

可以看出每个类都会通过继承链准备好自己的虚函数列表,所谓的基类指针指向子类对象的多态特性,是通过保存在子类对象的虚函数表实现的
而非虚函数的调用,如最后的 pb->fun4(); 无法通过pb保存的对象的地址空间的信息确定调用哪个,所以只能根据pb的类型来确定 如果这样调用 ((Derive*)pb)->fun4();
则会输出Normal Derive::fun4(),调用Derive::fun4()。
由此可知普通函数调用编译器根据指针类型来确定,虚函数调用编译器根据对应类的虚函数表确定。
*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值