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

谈面向对象语言不能不谈继承,这也是面向对象语言天生的优势,大大提高了代码的复用,在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          

                                  

扫描二维码关注公众号,回复: 125314 查看本文章

    总结:                                    

                                        

    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

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



猜你喜欢

转载自blog.csdn.net/u013372900/article/details/77923140
今日推荐