2012-10-11 48 views
-6

什么是C++类的数据结构? 它如何在装配层面上工作?类的数据结构

IF语句是代码行的比较+条件跳转。

数组和字符串是数据链式链接。

+4

你到底在问什么? – IronMan84

+2

'if'≠'jump'。至少,'if' ='compare' +'条件跳转'。一个类通常是一个数据结构,包含数据,指向该类的虚拟方法的指针以及指向该类祖先类(如果有的话)的指针。 –

+0

C++类的数据结构是什么? – wizztjh

回答

3

编译器分配偏移的所有成员,包括这些上成员的所有加载/存储操作:

struct foo { 
    uint32_t bar; 
    uint32_t baz; 

    uint32_t get_baz() { return baz; } 
}; 

uint32_t get_baz_from_foo(foo *f) { return f->baz; } 

变为(用于简单ARM汇编代码):

foo__get_baz: 
    ; calling convention: this pointer in r3 
    ; load 32 bit value from r3 + 4 bytes into r0 
    ldr r0, [r3, #4]; 
    ; calling convention: return value in r0 
    ; return from subroutine 
    b lr 

get_baz_from_foo: 
    ; calling convention: first parameter in r0 
    ; load 32 bit value from r0 + 4 bytes into r0 
    ldr r0, [r0, #4] 
    ; calling convention: return value in r0 
    ; return from subroutine 
    b lr 

作为struct编译后各自的class布局不变,这里4硬编码成指令流。

创建实例的工作方式分配内存,并从分配函数传递指针大家期待的指针结构:

new__foo: 
    ; two 32 bit integers need 8 bytes 
    ; calling convention: first parameter in r0 
    mov r0, #8 
    ; call allocator, which will then return to the function invoking new 
    bra malloc 

如果有一个构造

struct foo2 { 
    foo2() : bar(5), baz(7) { } 
    uint32_t bar; 
    uint32_t baz; 
    uint32_t get_baz() { return baz; } 
}; 

我们结束用一种稍微更复杂的方式来创建对象(你应该能够弄清楚而没有评论):

new__foo2: 
    strdb lr, ![sp] 
    mov r0, #8 
    bl malloc 
    mov r1, #5 
    str r1, [r0] 
    mov r1, #7 
    str r1, [r0, #4] 
    ldaia lr, ![sp] 
    b lr 

get_baz的实现与foo类相同。

现在,如果我构造这样一个对象,并获得巴兹值:

bl new__foo2 
    ; remember: the this pointer goes to r3 
    mov r3, r0 
    bl foo2__get_baz 

我结束了包含值7r0

对于virtual方法,创建隐藏的数据成员,这是一个指向的功能的表:

struct base { 
    virtual uint32_t get_baz() = 0; 
}; 

struct derived : base { 
    derived() : baz(5) { } 
    virtual uint32_t get_baz(); 
    uint32_t bar; 
    uint32_t baz; 
}; 

变得

new__derived: 
    strdb lr, ![sp] 
    mov r0, #12 
    bl malloc 
    mov r1, #5 
    str r1, [r0, #8] 
    ; get the address of the vtable 
    ldr r1, =vtable__derived 
    ; vtable typically goes to the end of the class defining it 
    ; as this is the base class, it goes before derived's data members 
    str r1, [r0] 
    ldria lr, ![sp] 
    b lr 

vtable__derived: 
    ; pointer to function 
    dw derived__get_baz 

derived__get_baz: 
    ldr r0, [r3, #8] 
    b lr 

调用此函数间接完成:

; construct normally 
    bl new__derived 
    ; here, we forget that this is a "derived" object 
    ; this pointer to r3 
    mov r3, r0 
    ; get vtable ptr 
    ldr r0, [r3] 
    ; get function ptr from vtable 
    ldr r0, [r0] 
    ; call function 
    bl r0 

这里,r0现在是5,因为那是构造函数存储在那里的。