美文网首页
类的结构分析

类的结构分析

作者: 蓝胖子的梦 | 来源:发表于2020-09-14 16:07 被阅读0次

    类的结构分析

    引子:在程序世界中,无论接触哪门语言,类是最基本一个研究点。那么在oc中,类和类的结构是如何组成的呢?

    类的isa走位图

    avatar
    • 实例对象的isa指向类
    • 类对象的isa指向元类
    • 元类对象的isa指向根元类
    • 根元类对象的isa指向自己本身
      另外从继承角度看:
    • 子类subclass继承父类superclass;父类superclass继承根类rootclass(根类);根类rootclass继承nil
    • 子类的元类继承父类的元类;父类的元类继承根类的元类;根类的元类继承根类;

    通过clang命令,生成xxx.cpp文件

        clang -rewrite-objc LGPerson.m -o LGPerson.cpp
    
    struct LGPerson_IMPL {
        struct NSObject_IMPL NSObject_IVARS;
        short _aa;
        short _bb;
        short _cc;
    };
    
    struct NSObject_IMPL {
        Class isa;
    };
    
    typedef struct objc_class *Class;
    
    //objc-runtime-new.h
    struct objc_class : objc_object {
        // Class ISA;
        Class superclass;
        cache_t cache;             // formerly cache pointer and vtable
        class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    
        class_rw_t *data() const {
            return bits.data();
        }
        ...
        ...
        
    //objc-private.h    
    struct objc_object {
    private:
        isa_t isa;    
    
    • 通过分析xxx.cpp和objc4-781源码文件分析,我们可以得出以下一些信息。
    • 在oc上层,所有类都是继承自NSObject。但是到了底层(c/c++)则是objc_class、objc_object;
    • 所有的类都是以objc_class为模板继承来的;所有对象都是以objc_object为模板继承来的。
    • 所有的对象、类、元类都有isa指针,万物皆对象。
    • 类在内存中只存在一份

    objc_object、objc_class、isa关系图

    -w1273
    • id=objc_object:isa_t、关于isa相关操作、弱引用相关、关联对象、内存管理
    • class=objc_class:objc_class继承自objc_object,Class superclass,cache_t cache,class_data_bits_t bits.
    • isa_t 共用体,64位,分为指针型isa,全部位数为指针地址;非指针型isa,部分位数为指针地址。
    • class_data_bits_t:主要是对class_rw_t的封装,class_rw_t是类读写(protocol、propertys、methods)相关信息,对class_ro_t的封装
    (lldb) p/x LGPerson.class
    (Class) $0 = 0x0000000100003420 LGPerson
    (lldb) x/4gx 0x0000000100003420
    0x100003420: 0x00000001000033f8 0x0000000100335140
    0x100003430: 0x000000010066d6b0 0x0002802400000003
    (lldb) p (class_data_bits_t *)0x100003440
    (class_data_bits_t *) $1 = 0x0000000100003440
    (lldb) p $1->data()
    (class_rw_t *) $2 = 0x000000010066d630
    (lldb) p *$2
    (class_rw_t) $3 = {
      flags = 2148007936
      witness = 1
      ro_or_rw_ext = {
        std::__1::atomic<unsigned long> = 4294980072
      }
      firstSubclass = nil
      nextSiblingClass = NSUUID
    }
    (lldb) p $3.properties()
    (const property_array_t) $4 = {
      list_array_tt<property_t, property_list_t> = {
         = {
          list = 0x0000000100003320
          arrayAndFlag = 4294980384
        }
      }
    }
    (lldb) p $4.list
    (property_list_t *const) $5 = 0x0000000100003320
    (lldb) p *$5
    (property_list_t) $6 = {
      entsize_list_tt<property_t, property_list_t, 0> = {
        entsizeAndFlags = 16
        count = 1
        first = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
      }
    }
    (lldb) p $3.methods
    (const method_array_t) $7 = {
      list_array_tt<method_t, method_list_t> = {
         = {
          list = 0x0000000100003230
          arrayAndFlag = 4294980144
        }
      }
    }
      Fix-it applied, fixed expression was: 
        $3.methods()
    (lldb) p $7.list
    (method_list_t *const) $8 = 0x0000000100003230
    (lldb) p *$8
    (method_list_t) $9 = {
      entsize_list_tt<method_t, method_list_t, 3> = {
        entsizeAndFlags = 26
        count = 4
        first = {
          name = "sayHello"
          types = 0x0000000100001f7d "v16@0:8"
          imp = 0x0000000100001cc0 (KCObjc`-[LGPerson sayHello])
        }
      }
    }
    (lldb) 
    

    相关文章

      网友评论

          本文标题:类的结构分析

          本文链接:https://www.haomeiwen.com/subject/mcpzektx.html