zoukankan      html  css  js  c++  java
  • class的本质

    在OC中,类对象(class对象)和元类对象(meta-class对象)的本质结构都是struct objc_class指针,即在内存中就是结构体。

    Class clas = [NSObject class];   
    

    来到class底层源码,我们可以看到:

    typedef struct objc_class *Class;
    

    class对象其实是一个objc_class结构体的指针。因此我们可以说类对象或元类对象在内存中其实就是objc_class结构体。

    相信很多人在查看源码或者看一些底层博客的时候,经常会看到下面一段代码,来讲述class的内部结构:

    typedef struct objc_class *Class;
    
    struct objc_class {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    
    #if !__OBJC2__
        Class _Nullable super_class                              OBJC2_UNAVAILABLE;
        const char * _Nonnull name                               OBJC2_UNAVAILABLE;
        long version                                             OBJC2_UNAVAILABLE;
        long info                                                OBJC2_UNAVAILABLE;
        long instance_size                                       OBJC2_UNAVAILABLE;
        struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
        struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
        struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
        struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
    #endif
    
    } OBJC2_UNAVAILABLE;
    
    

    这段源码其实讲述的也是class内部结构,包含成员变量列表方法列表方法缓存以及协议列表。细心的人可能会发现,这段代码里面是有if判断条件的:

    #if !__OBJC2__
    

    在结尾处也有:

    OBJC2_UNAVAILABLE
    

    判断条件是非OC2.0版本,也就是说在OC2.0之前的版本中,class底层的结构体中包含上面代码所讲述的,但我们现在所用的最新版肯定是OC2.0版本了,所以这段代码就不再使用了。

    那么新的class底层源码是什么样子呢?我们截取objc源码中objc_class结构体部分内容:

    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() { 
            return bits.data();
        }
    

    我们发现objc_class结构体继承 objc_object并且结构体内有一些函数,因为这是c++结构体,在c上做了扩展,因此结构体中可以包含函数。注意观察注释掉的Class ISA这一行代码:

        // Class ISA;
    

    我们来到objc_object内,继续截取部分代码:

    struct objc_object {
    private:
        isa_t isa;
    
    public:
    
        // ISA() assumes this is NOT a tagged pointer object
        Class ISA();
    
        // getIsa() allows this to be a tagged pointer object
        Class getIsa();
    

    我们发现objc_object中有一个isa指针,那么objc_class继承objc_object,也就同样拥有一个isa指针。继承来了isa指针,所以上文我们提到了Class ISA也就被注释掉了。

    看完源码,那么我们来分析一下class底层的objc_class结构体:

    objc_class结构体

    可以看到结构体中只包含isasuperclasscachebits。而在上文的源码中有这样一个方法:

        class_rw_t *data() { 
            return bits.data();
    

    也就是说class_rw_t是通过bits调用data方法得来的,我们来到data方法内部实现:

    class_rw_t* data() {
            return (class_rw_t *)(bits & FAST_DATA_MASK);
        }
    

    我们可以看到,data函数内部仅仅对bits进行&FAST_DATA_MASK操作,会得到class_rw_t这样一个结构体:

    class_rw_t.jpeg

    rw代表readwrite,可读可写
    t代表table,列表

    struct class_rw_t结构体中就包含了方法列表、属性列表以及协议列表,这些都是可读可写的。其中还包含一个struct class_ro_t的结构体:

    class_ro_t.jpeg

    ro代表readonly,只读

    struct class_ro_t的结构体中包含了instance对象占用的内存空间、类名以及成员变量列表,当然这些都是只读的。

    最后我们用一张图来总结一下struct objc_class的结构:

    struct objc_class内部结构.png

  • 相关阅读:
    第2课:关闭被黑客扫描的端口
    CentOS安装zip及用法
    网络安全目录
    第1课:电脑基础命令讲解
    SQL注入目录
    windows下安装redis
    CentOS安装rar及用法
    CentOS安装OpenOffice
    hadoop异常
    删除CentOS系统自带的jdk
  • 原文地址:https://www.cnblogs.com/r360/p/15741154.html
Copyright © 2011-2022 走看看