Chinaunix首页 | 论坛 | 博客
  • 博客访问: 19261
  • 博文数量: 9
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 95
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-21 12:21
文章分类
文章存档

2011年(1)

2010年(3)

2009年(5)

我的朋友

分类: C/C++

2009-12-06 09:34:03

来看下面的一段代码:
#include
class CShape
{
public:
    CShape();
    ~CShape();
   
public:
    virtual void print();
};
 
CShape::CShape()
{
}
 
CShape::~CShape()
{
}
 
void CShape::print()
{
    printf("CShape::print\n");
}
 
class CRect : public CShape
{
public:
    CRect();
    ~CRect();
   
public:
    virtual void print();
};
 
CRect::CRect()
{
}
 
CRect::~CRect()
{
}
 
void CRect::print()
{
    printf("CRect::print\n");
}
 
class CSquare : public CShape
{
public:
    CSquare();
    ~CSquare();
   
public:
    virtual void print();
};
 
CSquare::CSquare()
{
}
 
CSquare::~CSquare()
{
}
 
void CSquare::print()
{
    printf("CSquare::print\n");
}
 
int main(int args, char** argv)
{
    CShape* shape;
    CRect rect;
    CSquare square;
   
    shape = ▭
    shape->print();
   
    shape = □
    shape->print();
   
    return 0;
}
 
对应的汇编代码如下:
    .file   "class.c"
    .text
    .align 2
.globl __ZN6CShapeC2Ev
    .def    __ZN6CShapeC2Ev;    .scl    2;  .type   32; .endef
__ZN6CShapeC2Ev:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movl    $__ZTV6CShape+8, (%eax)
    popl    %ebp
    ret
    .align 2
.globl __ZN6CShapeC1Ev
    .def    __ZN6CShapeC1Ev;    .scl    2;  .type   32; .endef
__ZN6CShapeC1Ev:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movl    $__ZTV6CShape+8, (%eax)
    popl    %ebp
    ret
    .align 2
.globl __ZN6CShapeD2Ev
    .def    __ZN6CShapeD2Ev;    .scl    2;  .type   32; .endef
__ZN6CShapeD2Ev:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movl    $__ZTV6CShape+8, (%eax)
    popl    %ebp
    ret
    .align 2
.globl __ZN6CShapeD1Ev
    .def    __ZN6CShapeD1Ev;    .scl    2;  .type   32; .endef
__ZN6CShapeD1Ev:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    movl    $__ZTV6CShape+8, (%eax)
    popl    %ebp
    ret
    .section .rdata,"dr"
LC0:
    .ascii "CShape::print\12\0"
    .text
    .align 2
.globl __ZN6CShape5printEv
    .def    __ZN6CShape5printEv;    .scl    2;  .type   32; .endef
__ZN6CShape5printEv:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $LC0, (%esp)
    call    _printf
    leave
    ret
    .align 2
.globl __ZN5CRectC2Ev
    .def    __ZN5CRectC2Ev; .scl    2;  .type   32; .endef
__ZN5CRectC2Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeC2Ev
    movl    8(%ebp), %eax
    movl    $__ZTV5CRect+8, (%eax)
    leave
    ret
L11:
L10:
    .align 2
.globl __ZN5CRectC1Ev
    .def    __ZN5CRectC1Ev; .scl    2;  .type   32; .endef
__ZN5CRectC1Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeC2Ev
    movl    8(%ebp), %eax
    movl    $__ZTV5CRect+8, (%eax)
    leave
    ret
L14:
L13:
    .align 2
.globl __ZN5CRectD2Ev
    .def    __ZN5CRectD2Ev; .scl    2;  .type   32; .endef
__ZN5CRectD2Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    $__ZTV5CRect+8, (%eax)
L18:
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeD2Ev
    leave
    ret
L16:
    .align 2
.globl __ZN5CRectD1Ev
    .def    __ZN5CRectD1Ev; .scl    2;  .type   32; .endef
__ZN5CRectD1Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    $__ZTV5CRect+8, (%eax)
L23:
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeD2Ev
    leave
    ret
L21:
    .section .rdata,"dr"
LC1:
    .ascii "CRect::print\12\0"
    .text
    .align 2
.globl __ZN5CRect5printEv
    .def    __ZN5CRect5printEv; .scl    2;  .type   32; .endef
__ZN5CRect5printEv:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $LC1, (%esp)
    call    _printf
    leave
    ret
    .align 2
.globl __ZN7CSquareC2Ev
    .def    __ZN7CSquareC2Ev;   .scl    2;  .type   32; .endef
__ZN7CSquareC2Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeC2Ev
    movl    8(%ebp), %eax
    movl    $__ZTV7CSquare+8, (%eax)
    leave
    ret
L28:
L27:
    .align 2
.globl __ZN7CSquareC1Ev
    .def    __ZN7CSquareC1Ev;   .scl    2;  .type   32; .endef
__ZN7CSquareC1Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeC2Ev
    movl    8(%ebp), %eax
    movl    $__ZTV7CSquare+8, (%eax)
    leave
    ret
L31:
L30:
    .align 2
.globl __ZN7CSquareD2Ev
    .def    __ZN7CSquareD2Ev;   .scl    2;  .type   32; .endef
__ZN7CSquareD2Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    $__ZTV7CSquare+8, (%eax)
L35:
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeD2Ev
    leave
    ret
L33:
    .align 2
.globl __ZN7CSquareD1Ev
    .def    __ZN7CSquareD1Ev;   .scl    2;  .type   32; .endef
__ZN7CSquareD1Ev:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    $__ZTV7CSquare+8, (%eax)
L40:
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN6CShapeD2Ev
    leave
    ret
L38:
    .section .rdata,"dr"
LC2:
    .ascii "CSquare::print\12\0"
    .text
    .align 2
.globl __ZN7CSquare5printEv
    .def    __ZN7CSquare5printEv;   .scl    2;  .type   32; .endef
__ZN7CSquare5printEv:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $8, %esp
    movl    $LC2, (%esp)
    call    _printf
    leave
    ret
    .def    ___main;    .scl    2;  .type   32; .endef
    .def    __Unwind_SjLj_Resume;   .scl    2;  .type   32; .endef
    .def    ___gxx_personality_sj0; .scl    2;  .type   32; .endef
    .def    __Unwind_SjLj_Register; .scl    2;  .type   32; .endef
    .def    __Unwind_SjLj_Unregister;   .scl    2;  .type   32; .endef
    .align 2
.globl _main
    .def    _main;  .scl    2;  .type   32; .endef
_main:
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %edi
    pushl   %esi
    pushl   %ebx
    subl    $172, %esp
    andl    $-16, %esp
    movl    $0, %eax
    addl    $15, %eax
    addl    $15, %eax
    shrl    $4, %eax
    sall    $4, %eax
    movl    %eax, -156(%ebp)
    movl    -156(%ebp), %eax
    call    __alloca
    movl    $___gxx_personality_sj0, -100(%ebp)
    movl    $LLSDA24, -96(%ebp)
    leal    -92(%ebp), %eax
    leal    -24(%ebp), %edx
    movl    %edx, (%eax)
    movl    $L53, %edx
    movl    %edx, 4(%eax)
    movl    %esp, 8(%eax)
    leal    -124(%ebp), %eax
    movl    %eax, (%esp)
    call    __Unwind_SjLj_Register
    call    ___main
    leal    -56(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN5CRectC1Ev
    leal    -72(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN7CSquareC1Ev
    leal    -56(%ebp), %eax
    movl    %eax, -28(%ebp)
    movl    -28(%ebp), %eax
    movl    (%eax), %edx
    movl    -28(%ebp), %eax
    movl    %eax, (%esp)
    movl    (%edx), %eax
    movl    $1, -120(%ebp)
    call    *%eax
    leal    -72(%ebp), %eax
    movl    %eax, -28(%ebp)
    movl    -28(%ebp), %eax
    movl    (%eax), %edx
    movl    -28(%ebp), %eax
    movl    %eax, (%esp)
    movl    (%edx), %eax
    call    *%eax
    leal    -72(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN7CSquareD1Ev
    leal    -56(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN5CRectD1Ev
    movl    $0, -128(%ebp)
    jmp L44
L53:
    leal    24(%ebp), %ebp
    movl    -116(%ebp), %eax
    movl    %eax, -136(%ebp)
L45:
    movl    -136(%ebp), %edx
    movl    %edx, -132(%ebp)
    leal    -72(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN7CSquareD1Ev
    movl    -132(%ebp), %eax
    movl    %eax, -136(%ebp)
L47:
L49:
    movl    -136(%ebp), %edx
    movl    %edx, -140(%ebp)
    leal    -56(%ebp), %eax
    movl    %eax, (%esp)
    call    __ZN5CRectD1Ev
    movl    -140(%ebp), %eax
    movl    %eax, -136(%ebp)
L51:
    movl    -136(%ebp), %edx
    movl    %edx, (%esp)
    movl    $-1, -120(%ebp)
    call    __Unwind_SjLj_Resume
L44:
    leal    -124(%ebp), %eax
    movl    %eax, (%esp)
    call    __Unwind_SjLj_Unregister
    movl    -128(%ebp), %eax
    leal    -12(%ebp), %esp
    popl    %ebx
    popl    %esi
    popl    %edi
    popl    %ebp
    ret
    .section    .gcc_except_table,"dr"
LLSDA24:
    .byte   0xff
    .byte   0xff
    .byte   0x1
    .uleb128 LLSDACSE24-LLSDACSB24
LLSDACSB24:
    .uleb128 0x0
    .uleb128 0x0
LLSDACSE24:
    .text
.globl __ZTV7CSquare
    .section    .rdata$_ZTV7CSquare,"dr"
    .linkonce same_size
    .align 8
__ZTV7CSquare:
    .long   0
    .long   __ZTI7CSquare
    .long   __ZN7CSquare5printEv
.globl __ZTV5CRect
    .section    .rdata$_ZTV5CRect,"dr"
    .linkonce same_size
    .align 8
__ZTV5CRect:
    .long   0
    .long   __ZTI5CRect
    .long   __ZN5CRect5printEv
.globl __ZTV6CShape
    .section    .rdata$_ZTV6CShape,"dr"
    .linkonce same_size
    .align 8
__ZTV6CShape:
    .long   0
    .long   __ZTI6CShape
    .long   __ZN6CShape5printEv
.globl __ZTI6CShape
    .section    .rdata$_ZTI6CShape,"dr"
    .linkonce same_size
    .align 4
__ZTI6CShape:
    .long   __ZTVN10__cxxabiv117__class_type_infoE+8
    .long   __ZTS6CShape
.globl __ZTI5CRect
    .section    .rdata$_ZTI5CRect,"dr"
    .linkonce same_size
    .align 4
__ZTI5CRect:
    .long   __ZTVN10__cxxabiv120__si_class_type_infoE+8
    .long   __ZTS5CRect
    .long   __ZTI6CShape
.globl __ZTI7CSquare
    .section    .rdata$_ZTI7CSquare,"dr"
    .linkonce same_size
    .align 4
__ZTI7CSquare:
    .long   __ZTVN10__cxxabiv120__si_class_type_infoE+8
    .long   __ZTS7CSquare
    .long   __ZTI6CShape
.globl __ZTS6CShape
    .section    .rdata$_ZTS6CShape,"dr"
    .linkonce same_size
__ZTS6CShape:
    .ascii "6CShape\0"
.globl __ZTS5CRect
    .section    .rdata$_ZTS5CRect,"dr"
    .linkonce same_size
__ZTS5CRect:
    .ascii "5CRect\0"
.globl __ZTS7CSquare
    .section    .rdata$_ZTS7CSquare,"dr"
    .linkonce same_size
__ZTS7CSquare:
    .ascii "7CSquare\0"
    .def    _printf;    .scl    2;  .type   32; .endef
 
从以上汇编代码可以看出:
1、编译器自动创建一份构造函数和析构函数;
2、构造函数初始化顺序为先调用父类构造函数,再执行本类的构造函数;
3、析构函数析构顺序为先执行本类析构函数,再调用父类的析构函数;
4、编译器为拥有虚函数的类自动插入一个虚表,大小为4字节,是类的第一个成员变量,该变量是隐含的,对程序员不可见但是可以访问;
5、在创建类对象时,编译器将自动调用构造函数和析构函数;
6、函数调用时第一个参数为this指针,这是编译器自动插入的;
7、虚表保存着当前类和其父类的关系,通过这种关系可以确定this指针的指向关系,从而正确的调用虚函数(好像理解不是很正确,编译器一开始就应该知道当前this指针指向谁);
阅读(556) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~