Are classes structs or struct pointer

前端 未结 2 1072
野性不改
野性不改 2021-01-03 08:50

If I\'m not mistaken, structs mean objects, and struct pointers mean pointer to objects right? In an article, It says that classes are structs which means that they are obje

2条回答
  •  星月不相逢
    2021-01-03 09:18

    Classes are structs, but Class is a pointer type, being defined as

    typedef struct objc_class *Class;
    

    and this answers the first part of the question.

    Now, if you take a look at you'll find

    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;
    

    and in you'll find

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

    meaning that in Objective-C 2.0 objc_object and objc_class are identical structs, both having an isa field.

    That's why you can pass a Class where an id is required: classes are objects after all.

    You would normally expect a warning about the incompatible pointers type, but apparently the Obj-C compiler uses an ad-hoc treatment this specific case. I have no references to support this, though.

    EDIT

    I finally found a reference in the clang source code:

    In ASTContext.cpp, this is the Class declaration

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

    and this is the id declaration

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

    In both cases the type is set to the result of getObjCObjectPointerType. This causes the compiler to consider both Class and id as pointers to Objective-C objects.

提交回复
热议问题