iOS/Objective-C - struct objc_class*和struct objc_object*

 雨季莫犹忆 发布于 2023-02-07 10:29

我的理解是,对象Objective-C的只是结构.

他们分别只是:

struct objc_class *

和:

struct objc_object *

问题#1:

objc_msgSend(id self, SEL _cmd);

id 据我所知是类型 struct objc_object *

但是当我们调用类方法时,类是一个类struct objc_class *,

我希望它会引起问题或者喊出某种警告,例如"嘿,这里的错误类型,我的朋友".

但事实并非如此.

为什么?

这只是为了满足我的好奇心,因为即使没有完全理解这一点,它似乎也没有给我带来任何麻烦(到目前为止).但我想深入挖掘并学习基本原理/"特点".

问题2:

由于根据我的经验没有警告(与问题#1有关),因此我不太确定它们可以互换使用.

struct objc_class *struct objc_object * 真正使用互换

如是:

你能告诉我一个场景和样本何时/如何/为什么我们需要互换使用这些?

什么是好处(如果有的话),缺点(如果有的话)和" 陷阱 "(需要注意的事项;如果有的话)这样做?

Rob Napier.. 8

My understanding is that objects and classes in Objective-C are just structs.

This isn't really true, particularly since ObjC2, and definitely isn't a good way of thinking about it. The "struct" in question has a single field (isa) defined. That's it. It's a "struct" in name only.

Note that under ARC objects and structs are treated differently by the compiler. Objects pointers will get special handling (including nil-initialization) that a struct pointer will not. The compiler will also apply -> differently to an object than it does to a struct. A struct pointer must have a field with the name given after the ->. objc_object only has one field (isa). Since class hierarchies can be defined and redefined at runtime, the compiler cannot evaluate -> for an object at compile time as it does for a struct.

I make this point because in C++, objects and structs are just slightly different versions of the same thing, and you can easily swap between them. You cannot safely do that in ObjC. They're not nearly as similar.

But when we call a class method, a class, which is of type struct objc_class *, I would expect it to cause problem…

This is because classes are objects. Objects are not defined in terms of being of type objc_object. They're defined in terms of having an isa field (it used to be a pointer, but now it might be a pointer, or it might not). This is part of the problem of assuming that the typedef is the important thing. It isn't. What matters is whether it acts like an object. Objective-C is a mostly duck-typed language. If it acts like an object, it's an object.

BTW, NSProxy also lives in this weird almost-an-object world. If you note its definition, it does not inherit from anything, but it does declare an isa field as its first ivar. That's the critical part of making it act like an object.

Can struct objc_class * and struct objc_object * really be used interchangeably?

No. You can generally pass a class to anything that wants an object (since a class is an object), but you cannot pass an object to things that want a class.


KudoCC.. 5

我在runtime.h文件中找到它.

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;


struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

objc_class和objc_object都有isa变量,objc_object中的isa指向描述实例并存储实例方法列表的Class.objc_class中的Isa也指向Class,但它是描述类并存储类方法列表的元类.

该链接对您有用.

我已经模拟了病情.

struct A {
    int a ;
} ;

typedef struct A *PA ;

struct B {
    int a ;
    int b ;
} ;

void dosomething(PA pa)
{
    printf("%d", (*pa).a) ;
}

+ (void)hei
{
    struct B b ;
    b.a = 10 ;
    b.b = 20 ;
    // without forced cast, i will get a warning but work well
    dosomething((PA)&b) ;
}

您可以使用struct B *而不是struct A *因为编译器和链接器int a位于相同的相对地址中.

为什么编译器在我们调用传递struct objc_class *给它的类方法时不会抱怨objc_msgSend(id self, SEL _cmd);,在我看来编译器会考虑它.

2 个回答
  • 我在runtime.h文件中找到它.

    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;
    
    
    struct objc_object {
        Class isa  OBJC_ISA_AVAILABILITY;
    };
    

    objc_class和objc_object都有isa变量,objc_object中的isa指向描述实例并存储实例方法列表的Class.objc_class中的Isa也指向Class,但它是描述类并存储类方法列表的元类.

    该链接对您有用.

    我已经模拟了病情.

    struct A {
        int a ;
    } ;
    
    typedef struct A *PA ;
    
    struct B {
        int a ;
        int b ;
    } ;
    
    void dosomething(PA pa)
    {
        printf("%d", (*pa).a) ;
    }
    
    + (void)hei
    {
        struct B b ;
        b.a = 10 ;
        b.b = 20 ;
        // without forced cast, i will get a warning but work well
        dosomething((PA)&b) ;
    }
    

    您可以使用struct B *而不是struct A *因为编译器和链接器int a位于相同的相对地址中.

    为什么编译器在我们调用传递struct objc_class *给它的类方法时不会抱怨objc_msgSend(id self, SEL _cmd);,在我看来编译器会考虑它.

    2023-02-07 10:31 回答
  • My understanding is that objects and classes in Objective-C are just structs.

    This isn't really true, particularly since ObjC2, and definitely isn't a good way of thinking about it. The "struct" in question has a single field (isa) defined. That's it. It's a "struct" in name only.

    Note that under ARC objects and structs are treated differently by the compiler. Objects pointers will get special handling (including nil-initialization) that a struct pointer will not. The compiler will also apply -> differently to an object than it does to a struct. A struct pointer must have a field with the name given after the ->. objc_object only has one field (isa). Since class hierarchies can be defined and redefined at runtime, the compiler cannot evaluate -> for an object at compile time as it does for a struct.

    I make this point because in C++, objects and structs are just slightly different versions of the same thing, and you can easily swap between them. You cannot safely do that in ObjC. They're not nearly as similar.

    But when we call a class method, a class, which is of type struct objc_class *, I would expect it to cause problem…

    This is because classes are objects. Objects are not defined in terms of being of type objc_object. They're defined in terms of having an isa field (it used to be a pointer, but now it might be a pointer, or it might not). This is part of the problem of assuming that the typedef is the important thing. It isn't. What matters is whether it acts like an object. Objective-C is a mostly duck-typed language. If it acts like an object, it's an object.

    BTW, NSProxy also lives in this weird almost-an-object world. If you note its definition, it does not inherit from anything, but it does declare an isa field as its first ivar. That's the critical part of making it act like an object.

    Can struct objc_class * and struct objc_object * really be used interchangeably?

    No. You can generally pass a class to anything that wants an object (since a class is an object), but you cannot pass an object to things that want a class.

    2023-02-07 10:32 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有