4

如果我没记错的话,结构是指对象,结构指针是指指向对象的指针,对吗?在一篇文章中,它说类是结构,这意味着它们是对象。

Filter the list of all classes
The traditional definition of a class in Objective-C looks like this:

struct objc_class {
    Class isa;
    Class super_class;
    const char *name;
    long version;
    long info;
    long instance_size;
    struct objc_ivar_list *ivars;
    struct objc_method_list **methodLists;
    struct objc_cache *cache;
    struct objc_protocol_list *protocols;
    };

那么,如果它说类是结构,那么它们将如何适合objc_msgSend(id self, SEL_cmd)需要类型为 struct 指针的参数id

4

2 回答 2

9

类是结构,但是Class是指针类型,被定义为

typedef struct objc_class *Class;

这回答了问题的第一部分。

现在,如果你看看<objc/objc.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;

<obj/runtime.h>你会发现

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

这意味着在 Objective-C 2.0中objc_objectobjc_class它们是相同的结构,都具有一个isa字段。

这就是为什么你可以在需要的Class地方传递一个id类毕竟是对象

您通常会收到有关不兼容指针类型的警告,但显然 Obj-C 编译器在这种特定情况下使用了特别处理。 不过,我没有参考资料来支持这一点。

编辑

终于在clang源码中找到了参考:

ASTContext.cpp,这是Class声明

TypedefDecl *ASTContext::getObjCClassDecl() const {
  if (!ObjCClassDecl) {
    QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0);
    T = getObjCObjectPointerType(T);
    TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T);
    ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
                                        getTranslationUnitDecl(),
                                        SourceLocation(), SourceLocation(),
                                        &Idents.get("Class"), ClassInfo);
  }
  
  return ObjCClassDecl;
}

这是id声明

TypedefDecl *ASTContext::getObjCIdDecl() const {
  if (!ObjCIdDecl) {
    QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0);
    T = getObjCObjectPointerType(T);
    TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T);
    ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this),
                                     getTranslationUnitDecl(),
                                     SourceLocation(), SourceLocation(),
                                     &Idents.get("id"), IdInfo);
  }
  
  return ObjCIdDecl;
}

在这两种情况下,类型都设置为getObjCObjectPointerType. 这会导致编译器同时考虑Classid作为指向 Objective-C 对象的指针。

于 2013-10-19T18:06:49.997 回答
5

如果我没记错的话,结构是指对象,结构指针是指指向对象的指针,对吗?

大多数情况下,是的。但是由于在 Objective-C 中,对象(包括类)只能使用指针来操作,所以使用简写“对象”而不是更正确的“指向对象的指针”,即使在官方文档中也是如此。

所以,如果它说类是结构,那么它们将如何适应 的论点objc_msgSend()

它们将指针传递给作为对象的结构。Class是 的类型定义struct objc_class *,而id是 的类型定义struct objc_object *。两者都是(非函数)指针,并且两个结构都包含一个isa字段,只要您知道自己在做什么,它们就可以互换使用。

于 2013-10-19T18:18:50.613 回答