C++对象模型-ObjectSliced

2022-04-25 15:15:21 浏览数 (1)

开发环境

gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.10)

1, ObjectSliced

当一个base class object 被直接初始化(copy ctor)/赋值(operator =)为一个derived class object 时,derived object的base 部分会被切割(sliced)以塞入base type内存中,derived type将没有留下任何蛛丝马迹(即:base class object 的vptr不会被derived class object的vptr替换)

代码语言:javascript复制
#include<iostream>
using namespace std;
class ZooAnimal{
        public:
                ZooAnimal(int l):loc(l)
                {
                }
                virtual void print()
                {
                        cout<<"ZooAnimal";
                }
        private:
                int loc;
};
class Bear : public ZooAnimal{
        public:
                Bear(int c, int l):ZooAnimal(l), cell(c)
                {
                }
        private:
                void print()
                {
                        cout<<"Bear";
                }
        private:
                int cell;
};
int main()
{
        Bear b(1, 2);
        ZooAnimal z = b;
        z.print();
}

以上代码对应的汇编如下(g -S -m32 p27.cc):

代码语言:javascript复制
_ZN9ZooAnimalC2ERKS_: //ZooAnimal默认copy ctor
.LFB1031:
        .cfi_startproc
        pushl   �p
        .cfi_def_cfa_offset 8
        .cfi_offset 5, -8
        movl    %esp, �p
        .cfi_def_cfa_register 5
        movl    $_ZTV9ZooAnimal 8, �x //edx=ZooAnimal.vptr
        movl    8(�p), �x  //eax=[ebp 8],即eax=z.this
        movl    �x, (�x) //设置z的vptr
        movl    12(�p), �x //eax=b.this
        movl    4(�x), �x //edx = b.loc
        movl    8(�p), �x //eax=z.this
        movl    �x, 4(�x) //z.loc = b.loc
        nop
        popl    �p
        .cfi_restore 5
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
代码语言:javascript复制
main:
.LFB1029:
        .cfi_startproc
        leal    4(%esp), �x
        .cfi_def_cfa 1, 0
        andl    $-16, %esp
        pushl   -4(�x)
        pushl   �p
        .cfi_escape 0x10,0x5,0x2,0x75,0
        movl    %esp, �p
        pushl   �x
        .cfi_escape 0xf,0x3,0x75,0x7c,0x6
        subl    $36, %esp
        movl    %gs:20, �x
        movl    �x, -12(�p)
        xorl    �x, �x
        subl    $4, %esp
        pushl   $2
        pushl   $1
        leal    -24(�p), �x  //eax=ebp-24, b对象首地址
        pushl   �x  //b的首地址压栈,即b.this压栈
        call    _ZN4BearC1Eii //Bear::Bear(b.this, 1, 2)
        addl    $16, %esp
        subl    $8, %esp
        leal    -24(�p), �x //eax = ebps-24, 即eax=b.this
        pushl   �x //b.this压栈
        leal    -32(�p), �x //eax=ebp-32,即eax=z.this
        pushl   �x //z.this压栈
        call    _ZN9ZooAnimalC1ERKS_ //ZooAnimal::ZooAnimal(ZooAnimal const&)
        addl    $16, %esp
        subl    $12, %esp
        leal    -32(�p), �x //eax=z.this
        pushl   �x //z.this压栈
        call    _ZN9ZooAnimal5printEv  //ZooAnimal::print()
        addl    $16, %esp
        movl    $0, �x
        movl    -12(�p), �x
        xorl    %gs:20, �x
        je      .L8
        call    __stack_chk_fail
.L8:
        movl    -4(�p), �x
        .cfi_def_cfa 1, 0
        leave
        .cfi_restore 5
        leal    -4(�x), %esp
        .cfi_def_cfa 4, 4
        ret
        .cfi_endproc
2.图示
3.参考

《深度探索C 对象模型》

0 人点赞