反汇编分析之:继承,多重继承,多层继承,父子类指针本质

来源:互联网 发布:sqlserver删除主键 编辑:程序博客网 时间:2024/06/06 09:18

谈面向对象语言不能不谈继承,这也是面向对象语言天生的优势,大大提高了代码的复用,在c语言中我们也可以通过结构体嵌套的方式,来实现继承,倘若看本c++的书,一个继承都能来来回回讲个几十回合。我们通过反汇编来看看继承的本质究竟是什么?

 

一:继承                                    

                                        

    1、不继承的写法                                

   

                                         struct Person                                        {                                            int age;                                        int sex;                                    };                                        struct Teacher                                        {                                            int age;                                        int sex;                                        int level;                                        int classId;                                    };                                        struct Student                                        {                                            int age;                                        int sex;                                        int code;                                        int score;                                    };                                                                                                                        Teacher t;                观察反汇编:                                                                t.age = 1;                  mov dword ptr [ebp-10h],1                        t.sex = 2;                  mov dword ptr [ebp-0Ch],2                        t.level = 3;                mov dword ptr [ebp-8],3                        t.classId = 4;              mov dword ptr [ebp-4],4                                                    push 10h                        printf("%d\n",sizeof(t));                push offset string "%d\n" (0042201c)                                                    call printf (004010e0)                                                    add esp,8                                                     Student s;                mov dword ptr [ebp-10h],1                                                  mov dword ptr [ebp-0Ch],2                        s.age = 1;                mov dword ptr [ebp-8],3                        s.sex = 2;                mov dword ptr [ebp-4],4                        s.code = 3;               push 10h                        s.score = 4;              push offset string "%d\n" (0042201c)                                                  call printf (004010e0)                        printf("%d\n",sizeof(s));                add esp,8    

                                    

    2、改变写法:        继承方式                            

   

 struct Person                                        {                                            int age;                                        int sex;                                    };                                        struct Teacher:Person                                        {                                            int level;                                        int classId;                                    };                                        struct Student:Person                                        {                                            int code;                                        int score;                                    };                                    反汇编:                                                            Teacher t;                mov dword ptr [ebp-10h],1                                                  mov dword ptr [ebp-0Ch],2                        t.age = 1;                mov dword ptr [ebp-8],3                        t.sex = 2;                mov dword ptr [ebp-4],4                        t.level = 3;              push 10h                        t.classId = 4;            push offset string "%d\n" (0042201c)                                                 call printf (004010e0)                        printf("%d\n",sizeof(t));                add esp,8                                                                                      Student s;                mov dword ptr [ebp-10h],1                                                  mov dword ptr [ebp-0Ch],2                        s.age = 1;                mov dword ptr [ebp-8],3                        s.sex = 2;                mov dword ptr [ebp-4],4                        s.code = 3;               push 10h                        s.score = 4;              push offset string "%d\n" (0042201c)                                        call printf (004010e0)                        printf("%d\n",sizeof(s));                add esp,8          

                                 

    总结:                                    

                                        

    1、什么是继承?                                    

                                        

    继承就是数据的复制,从汇编的角度看是,完全一样的,但是从编写的角度看,显然继承的方式编写大大提高了代码的复用

其实本质上,就是继承的时候,那部分继承代码会由编译器帮我们生成而不用我们自己编写,这也是为什么说,继承的本质就是数据的复制,其实就是将父类的拷贝到子类。                                    

                                   

   2、为什么要用继承?                                                                        

    减少重复代码的编写                                    

                                        

    3、Person 称为父类或者基类                                    

                                        

    4、Teacher、Student称为子类或者派生类                                    

                                        

    5、t和s可以称为对象或者实例.                                    

                                        

    6、可以用父类指针指向子类的对象.    

这是我们要讨论的一个核心问题,那就是类指针,其实上面的东西明白了,类指针也就非常明白了。下面的代码实现了父类指针指向子类

而且可以访问修改,这其实就是源于继承的本质,从内存的角度来看,继承的父类成员放在了对象的开始,低地址处,父类指针和子类指针的区别

最为明显的就是指针步长的不同,而把父类指针指向开始,恰好是父类的成员,符合父类的指针步长,也就恰好可以访问。当然世间没有那么多的恰好

这必然是源于语言设计者的心血。那么可否用父类指针访问子类成员,编译器是不允许的,这还是源于指针步长的合理性,当然从底层的角度来看,没有什么不能访问,我们可以通过一些手段来实现访问。反过来,子类指针访问父类,其实是没有什么价值的,源于父类里面没有子类的成员。而且编译器肯定是不允许的。

 

 




 

  


#include <iostream> using namespace std ;     struct Person            {                int age;            int sex;        };            struct Teacher:Person            {                int level;            int classId;        };            struct Student:Person            {                int code;            int score;        };                         int main (void){     Teacher *point, t;                point=&t;     point->age=1;    point->classId=2;    point->level=3;    point->sex=4;                printf("%d %d %d %d\n",t.age,t.classId,t.level,t.sex);            Person * point_test; // 父类指针    point_test=&t; // 子类对象地址     point_test->age=5;    point_test->sex=6;        printf("%d %d\n",t.age,t.sex);            return 0;}


二:      多层继承

 

多层继承比较简单,那就是你可以继承你父亲的遗产,也可以继承你爷爷的遗产。其实都可以想到,还是数据的拷贝。

                            

  










 

    多层继承:                观察反汇编:                1)无相同成员                                struct X                                {                 mov dword ptr [ebp-18h],1                    int a;            mov dword ptr [ebp-14h],2                    int b;            mov dword ptr [ebp-10h],3                };                 mov dword ptr [ebp-0Ch],4                struct Y:X            mov dword ptr [ebp-8],5                {                 mov dword ptr [ebp-4],6                    int c;            push 18h                    int d;            push offset string "%d\n" (0042201c)                };                 call printf (004010e0)                struct Z:Y                add esp,8                {                                    int e;                                int f;                            };                                                                                                Z z;                                                                z.a = 1;                                z.b = 2;                                z.c = 3;                                z.d = 4;                                z.e = 5;                                z.f = 6;                                                                printf("%d\n",sizeof(z));                                                                                                  2)有相同成员 ,二异性问题 ,但是编译器不一定会报错,默认是使用当前类的成员                                                                                          struct X                                {                                    int a;                                int b;                            };                                struct Y:X                                {                                    int a;                                int d;                            };                                struct Z:Y                                {                                    int e;                                int f;                            };                                                                                                                                Z z;                                                                z.X::a = 1;    //通过::区分了a,但是对于底层来说和上面的完全一样,                   //这里的区分仅仅是让编译器明白。                    z.b = 2;                                z.Y::a = 3;                                z.d = 4;                                z.e = 5;                                z.f = 6;                                                                printf("%d\n",sizeof(z));                                printf("%d\n",z.X::a);                                printf("%d\n",z.b);                                printf("%d\n",z.Y::a);                                printf("%d\n",z.d);                                printf("%d\n",z.e);                                printf("%d\n",z.f);                             


 对于二义性问题,其本质是不存在任何问题的,从汇编看,和正常的成员完全一样,关键的就是让编译器可以区分。

三:多重继承

何为多重继承,就是有多个爹,在java 中是没有多重继承的,但是在c++中是支持多重继承的。也就是一个父类有多个子类。

 

 













   3、继承的特性            struct X            {                int a;            int b;        };            struct Y            {                int c;            int d;        };            struct Z:X,Y            {                int e;            int f;        };         

——————————————————2017年9月10日17:45:29

其实我要说的是,有时候概念多了反而不是什么好事,也许事物的本质就一种。



原创粉丝点击