Onelong

分享知识,与你一起进步......
RSS icon Home icon
  • C++ 虚函数

    post by onelong / 2012-12-22 23:29 Saturday [C++]

    C++代码:

     

    class Object

    {

    private:

    int num;

    public:

    Object()

    {

    num = 50;

    }

     

    virtual int getNum() //虚函数

    {

    return num;

    }

     

    ~Object()

    {

    num = 0;

    }

    }; 

    int main()

    {

    Object *p = new Object();

    p->getNum();

    delete p;

    return 0;

    }

    汇编代码:

     

    .arch armv4t

    .fpu softvfp

    .eabi_attribute 20, 1

    .eabi_attribute 21, 1

    .eabi_attribute 23, 3

    .eabi_attribute 24, 1

    .eabi_attribute 25, 1

    .eabi_attribute 26, 2

    .eabi_attribute 30, 6

    .eabi_attribute 18, 4

    .file "person.cpp"

    .section .text._ZN6ObjectC1Ev,"axG",%progbits,_ZN6ObjectC1Ev,comdat

    .align 2

    .weak _ZN6ObjectC1Ev

    .type _ZN6ObjectC1Ev, %function

    _ZN6ObjectC1Ev:

    .fnstart

    .LFB2:

    @ Function supports interworking.

    @ args = 0, pretend = 0, frame = 8

    @ frame_needed = 1, uses_anonymous_args = 0

    @ link register save eliminated.

    str fp, [sp, #-4]!

    .LCFI0:

    add fp, sp, #0

    .LCFI1:

    sub sp, sp, #12

    .LCFI2:

    str r0, [fp, #-8]

    ldr r3, [fp, #-8]

    ldr r2, .L4 //构造函数突然多了这个?

    str r2, [r3, #0]

    ldr r3, [fp, #-8]

    mov r2, #50

    str r2, [r3, #4]

    ldr r3, [fp, #-8]

    mov r0, r3

    add sp, fp, #0

    ldmfd sp!, {fp}

    bx lr

    .L5:

    .align 2

    .L4:

    .word _ZTV6Object+8 //+8的地方是什么的?

    .LFE2:

    .cantunwind

    .fnend

    .size _ZN6ObjectC1Ev, .-_ZN6ObjectC1Ev

    .section .text._ZN6Object6getNumEv,"axG",%progbits,_ZN6Object6getNumEv,comdat

    .align 2

    .weak _ZN6Object6getNumEv

    .type _ZN6Object6getNumEv, %function

    _ZN6Object6getNumEv:

    .fnstart

    .LFB3:

    @ Function supports interworking.

    @ args = 0, pretend = 0, frame = 8

    @ frame_needed = 1, uses_anonymous_args = 0

    @ link register save eliminated.

    str fp, [sp, #-4]!

    .LCFI3:

    add fp, sp, #0

    .LCFI4:

    sub sp, sp, #12

    .LCFI5:

    str r0, [fp, #-8]

    ldr r3, [fp, #-8]

    ldr r3, [r3, #4]

    mov r0, r3

    add sp, fp, #0

    ldmfd sp!, {fp}

    bx lr

    .LFE3:

    .cantunwind

    .fnend

    .size _ZN6Object6getNumEv, .-_ZN6Object6getNumEv

    .section .text._ZN6ObjectD1Ev,"axG",%progbits,_ZN6ObjectD1Ev,comdat

    .align 2

    .weak _ZN6ObjectD1Ev

    .type _ZN6ObjectD1Ev, %function

    _ZN6ObjectD1Ev:

    .fnstart

    .LFB6:

    @ Function supports interworking.

    @ args = 0, pretend = 0, frame = 8

    @ frame_needed = 1, uses_anonymous_args = 0

    @ link register save eliminated.

    str fp, [sp, #-4]!

    .LCFI6:

    add fp, sp, #0

    .LCFI7:

    sub sp, sp, #12

    .LCFI8:

    str r0, [fp, #-8]

    ldr r3, [fp, #-8]

    ldr r2, .L11 //??

    str r2, [r3, #0]

    ldr r3, [fp, #-8]

    mov r2, #0

    str r2, [r3, #4]

    ldr r3, [fp, #-8]

    mov r0, r3

    add sp, fp, #0

    ldmfd sp!, {fp}

    bx lr

    .L12:

    .align 2

    .L11:

    .word _ZTV6Object+8//??

    .LFE6:

    .cantunwind

    .fnend

    .size _ZN6ObjectD1Ev, .-_ZN6ObjectD1Ev

    .text

    .align 2

    .global main

    .type main, %function

    main:

    .fnstart

    .LFB7:

    @ Function supports interworking.

    @ args = 0, pretend = 0, frame = 8

    @ frame_needed = 1, uses_anonymous_args = 0

    stmfd sp!, {r4, fp, lr}

    .save {r4, fp, lr}

    .LCFI9:

    .setfp fp, sp, #8

    add fp, sp, #8

    .LCFI10:

    .pad #12

    sub sp, sp, #12

    .LCFI11:

    mov r0, #8

    bl _Znwj

    mov r3, r0

    mov r4, r3

    mov r3, r4

    mov r0, r3

    bl _ZN6ObjectC1Ev //调用构造函数

    str r4, [fp, #-16]

    ldr r3, [fp, #-16]

    ldr r3, [r3, #0]

    ldr r3, [r3, #0]

    ldr r0, [fp, #-16]

    mov lr, pc

    bx r3 //跳转方式不同了?不是直接调用getNum了,为什么呢?

    ldr r4, [fp, #-16]

    cmp r4, #0

    beq .L15

    .L16:

    .L14:

    mov r0, r4

    bl _ZN6ObjectD1Ev //调用析构函数

    mov r0, r4

    bl _ZdlPv //释放内存

    .L15:

    mov r3, #0

    mov r0, r3

    sub sp, fp, #8

    ldmfd sp!, {r4, fp, lr}

    bx lr

    .LFE7:

    .fnend

    .size main, .-main

    .weak _ZTV6Object

    .section .rodata._ZTV6Object,"aG",%progbits,_ZTV6Object,comdat

    .align 3

    .type _ZTV6Object, %object

    .size _ZTV6Object, 12

    _ZTV6Object:

    .word 0

    .word _ZTI6Object

    .word _ZN6Object6getNumEv

    .weak _ZTS6Object

    .section .rodata._ZTS6Object,"aG",%progbits,_ZTS6Object,comdat

    .align 2

    .type _ZTS6Object, %object

    .size _ZTS6Object, 8

    _ZTS6Object:

    .ascii "6Object\000"

    .weak _ZTI6Object

    .section .rodata._ZTI6Object,"aG",%progbits,_ZTI6Object,comdat

    .align 2

    .type _ZTI6Object, %object

    .size _ZTI6Object, 8

    _ZTI6Object:

    .word _ZTVN10__cxxabiv117__class_type_infoE+8

    .word _ZTS6Object

    .ident "GCC: (ctng-1.6.1) 4.4.3"

    .section .note.GNU-stack,"",%progbits

    有了虚函数后,编译的结果变了,并不像我们想象的那样了!虚函数到底是怎样存放的呢?对像我这样的初学者当然是不懂的。于是曾经的技术总监发过我一些资料。关于vtable这个东东的

    http://en.wikipedia.org/wiki/Vtable

    http://haoel.blog.51cto.com/313033/124595/

    在那些资料上可以知道,虚函数和函数处理方式的不同的。下次对比一下纯虚函数才行。虚函数放到vtable,普通的函数还是老样子,代码跳转,看构造函数,析构函数就知道了。

    在上面的资料里面,有提到了一些内存布局的点点,尽管不太全面,有兴趣的孩子可以找其他相关资料吧,曾经总监给我的资料被墙了,非常抱歉无法分享。

    上面有什么不合理的,请高手指点吧。初学者的成长需要您的一点阳光

    http://www.cnblogs.com/zhyg6516/archive/2011/03/07/1974423.html

    晚上回去对了一下,纯虚函数也差不多这样。含有纯虚函数的是抽象类而已,不能实例化。

    和java对比一下:

    java的成员方法默认都是类似C++的虚函数。

    接口里面的方法更像是纯虚函数,抽象类的方法也类似c++的虚函数

    引用地址:
     

    我要评论