V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
acumen
V2EX  ›  C

关于 OC 底层的一个问题

  •  
  •   acumen · 2016-10-20 22:06:24 +08:00 · 2248 次点击
    这是一个创建于 2985 天前的主题,其中的信息可能已经有所发展或是发生改变。

    学习《 Objective-C 高级编程: iOS 与 OS X 多线程和内存管理》书中 98 页时,有几个疑问。

    1. 通过成员变量 isa 保持该类的结构体实例指针。这句话怎么理解?
    2. 关于图中 class_t 结构体怎么理解?(我的理解:是每个 OC 对象的实例所对应的结构体‘模版’?)

    下图是书的内容

    望大神指点。

    13 条回复    2016-10-21 19:46:29 +08:00
    coa
        1
    coa  
       2016-10-21 00:03:51 +08:00
    Objective C 基于 C 的基础上拓展出面对对象特性,所以该段实际上是把先假设你有 C 的基础来解释它的内部原理。试着返回去跳过 C 的内容直接来看:

    1.“通过成员变量 isa 保持该类的结构体实例指针。”——直接用 OC 来描述就是:每一个初始化出来的实例,内部都有一个名为 isa 的指针指向它的类。类其实也是“对象”,把它称为“类对象”也未尝不可,在内存上表现和实例对象一毛一样。

    2.“关于图中 class_t 结构体怎么理解?”——直接理解为实例的模板没错,或者说,抛开它 C 的解释,这就是类。这里 objc_class 和 class_t 可能会造成一些混淆,看起来 object_class 内部只是定义了 isa 指针, class_t 才是在这基础上增加定义了函数指针等其他东西,所以 class_t 才是和类相对应的。

    当你向一个实例发送消息时,它会找到 isa 指向的地址,即类,类里存着所有消息名(选择器)和函数地址的对应列表,找到对应的函数并调用,就完成了一次消息发送。灵活地操作这过程就能实现 runtime 的各种黑魔法。

    总而言之 OC 对象是在 C 的结构体上做了类型定义(当然内部实现肯定不止这么简单),你看到 objc_object 结构体直接当成实例对象,看到 class_t 结构体直接当成类就行。

    这书是很久以前看过一部分,可能存在一些理解上的偏颇,仅供参考。
    acumen
        2
    acumen  
    OP
       2016-10-21 00:39:09 +08:00 via iPhone
    @coa 感谢你的解答,很详细。第一点想明白了。
    第二点,我所了解的 objc_object 中的 isa 指向的是 objc_class 接下去 objc_class 其中的 isa 指向谁呢?
    对于 oc 每个具体的类对应一个 meta-class , meta-class 其实也是基于 class_t ?这样说的话 class_t 就是所有对象的所对应的最底层的一个结构体了?

    我的理解不知道有没有问题?
    coa
        3
    coa  
       2016-10-21 09:15:23 +08:00
    objc_class 的 isa 指向 meta class 。 class 定义了实例方法的实现, meta class 定义了类方法的实现,这样实例方法和类方法都能通过 isa 实现消息发送。最末端的 isa 指向 NSObject ,而 NSObject 的 isa 指向自己。

    meta class 是为了让类方法也能通过 isa 进行消息传递,除了比 class 少了成员变量的定义,所以猜想除了这点外,底层内容应该确实是一样的。
    mofet
        4
    mofet  
       2016-10-21 09:53:11 +08:00
    http://www.jianshu.com/p/41735c66dccb
    看看这个,通俗易懂。
    Karsa
        5
    Karsa  
       2016-10-21 12:04:47 +08:00 via iPhone
    唉,电脑在恢复,本来想用手机简单聊一下的,然后发现越写越多,也是醉了,看来功夫还不到家,概括能力太弱。

    isa 建立 class 跟 meta class 之间关系, meta class 继承关系。对象的 isa 指向类的地址,类的 isa 指向自己的 meta class , meta class 的 isa 指向父类的地址,顶层 meta class 的 isa 指向自己。

    嗯,我记得应该是这样 ~
    Karsa
        6
    Karsa  
       2016-10-21 12:06:17 +08:00 via iPhone
    @Karsa 这些对象应该都是题主说的那个数据结构的实例,大概就是这样吧
    acumen
        7
    acumen  
    OP
       2016-10-21 12:14:37 +08:00
    @coa 我来总结一下,大神看看对不对。
    现在我们涉及到 objc_object , objc_class , isa , meta-class , class_t , NSObject 这几个。
    objc_object 其实就是我们常见的 id 在 C 语言中的表示, objc_object 结构体中的 isa 指向 objc_class , objc_class 中的 isa 指向 meta-class 。

    struct objc_class {
    Class isa OBJC_ISA_AVAILABILITY;

    #if !__OBJC2__
    Class super_class OBJC2_UNAVAILABLE;
    const char *name OBJC2_UNAVAILABLE;
    long version OBJC2_UNAVAILABLE;
    long info OBJC2_UNAVAILABLE;
    long instance_size OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
    struct objc_cache *cache OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
    #endif

    } OBJC2_UNAVAILABLE;

    这个是 objc.h 中 objc_class 的定义。这样说 meta-class 也是一个 objc_class 。
    class_t 这里就这样理解:其实每个对象和类,在 runtime 中都对应一个结构体,而生成这样的结构体需要一个‘模版’(这里解释了文中‘基于’的意思)。

    结合网上流传的这张图。这里的 instance of subclass 对应 objc_object , class 对应 objc_class , meta class 对应的还是 objc_class 。
    ![]( )

    至于 NSObject 所对应的 meta class 就是上图右上角的 root class ( meta )。

    卒.
    acumen
        8
    acumen  
    OP
       2016-10-21 12:17:29 +08:00
    @mofet 这篇博文, isa 指针是很清晰,我想弄明白的是,对象和类背后结构体之间的关系 并且和图中的对应关系。谢谢回复
    acumen
        9
    acumen  
    OP
       2016-10-21 12:20:46 +08:00
    @Karsa 你所说的 “ meta class 的 isa 指向父类的地址” ,应该是 meta class 的 isa 直接指向的是顶层的 meta class 吧
    acumen
        10
    acumen  
    OP
       2016-10-21 12:23:17 +08:00
    @Karsa 我认为也是这样,所有的对象都是 class_t 的实例。 但是这样的话。 class_t , objc_object , objc_class 这三者的关系又是如何呢。
    acumen
        11
    acumen  
    OP
       2016-10-21 17:45:11 +08:00   ❤️ 1
    http://blog.ibireme.com/2013/11/25/objc-object/
    http://stackoverflow.com/questions/15309497/understanding-objective-c-runtime/15309657#15309657

    由上面两个资料,大体上可以明白,或者说是猜想其中的机制。

    class_t 是 Class 的实际结构。和上面说的一样。在 runtime 中生成一个对应的结构体,其中的成员都是以 class_t 为标准。

    如果有更好的理解,欢迎分享啊~
    coa
        12
    coa  
       2016-10-21 19:15:28 +08:00
    其他关系都挺清晰了~自己也是没看明白这一页 objc_class 和 class_t 的关系,感觉 objc_object 后边接着 class_t 就挺顺畅的,不明白 objc_class 的作用~~不是纯 C 出身看这些源码看得好纠结~~ =。=
    acumen
        13
    acumen  
    OP
       2016-10-21 19:46:29 +08:00   ❤️ 1
    @coa 是啊,就是这一点不弄明白,感觉缺点什么。现在姑且 class_t 作为底层的结构体( stackoverflow 上那个歪果仁的意思好像是说 在最底层的 Class 和 class_t 指针之间可以强转,就说明结构体内的结构是一致的吧)。然后 “ instance of subclass 对应 objc_object , class 对应 objc_class , meta class 对应的还是 objc_class ” 按图来。在 runtime 中,像 objc_object 和 objc_class 的结构体都是动态按 class_t 生成的,所以也可以把所有对象的实例都是 class_t 结构体的实例。

    这样的思路好像也很清晰。就是不知道自己理解的有没有问题。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1059 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 18:14 · PVG 02:14 · LAX 10:14 · JFK 13:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.