对象与isa

2020-09-11  本文已影响0人  miaohy

对象本质是什么?(结构体)怎么证明呢?
首先了解一下clang,Clang是⼀个由Apple主导编写,基于LLVM的C/C++/Objective-C编译器
终端执行如下命令

clang -rewrite-objc LGPerson.m -o LGPerson.cpp

打开LGPerson.cpp,可以看到LGPerson被编译成了一个结构体,其中有isa指针

struct LGPerson_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct NSObject_IMPL {
    Class isa;
};

了解了对象的本质是结构体,那么结构体能被继承吗?通过在xcode中实际敲代码发现报错所以是不能被继承的。
但我们可以通过另外一种方式也就是伪继承的方式实现,如下coding

struct SuperPerson{
    int a;
};

struct SonPerson{ //大小等于a 4个字节 + b 4个字节 == 8个字节
    struct SuperPerson ll;
    int b;
};

那么如何调用呢?

 struct SuperPerson pp1;
  pp1.a = 10;
 struct SonPerson pp;
  pp.ll.a = 5;

如上所示我们成功的通过SonPerson访问了SuperPerson的成员

看到了结构体,再多吧啦点,结构体大小是怎样的呢?在内存是什么样子的呢?

NSLog(@"%lu %lu",sizeof(pp1), sizeof(pp));
2020-09-11 15:54:04.309319+0800 KCObjc[21290:479786] 4 8

isa指针会用到联合体,那么什么是联合体,与结构体区别是啥呢?

结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。
coding例子如下

union Person{
    char eye;
    struct{
        char eye_colr;
        BOOL show_eye;
    };
};

调用如下

 union Person person;
 person.eye = 's';
 person.eye_colr = 's';
 person.show_eye = false;
  NSLog(@"%lu",sizeof(person));
2020-09-11 16:46:48.744520+0800 KCObjc[22164:509122] 2

接下来看看对象成员isa相关
通过objc源码分析可以看到isa初始化过程
[LGPerson alloc]
objc_alloc_init
callAlloc
((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
alloc
_objc_rootAlloc
callAlloc
_objc_rootAllocWithZone
_class_createInstanceFromZone
initInstanceIsa
initIsa
ASSERT(!isTaggedPointer());
isa_t

newisa.bits = ISA_MAGIC_VALUE;
newisa.has_cxx_dtor = hasCxxDtor;
newisa.shiftcls = (uintptr_t)cls >> 3; //uintptr是什么?主要用于指针的按位操作,因为不能对指针执行按位操作,为了对指针执行按位操作,需要将指针转换为unitpr类型
 isa = newisa;

p newisa
(isa_t) $7 = {
  cls = LGPerson
  bits = 8303516107940229
   = {
    nonpointer = 1
    has_assoc = 0
    has_cxx_dtor = 1
    shiftcls = 536871984
    magic = 59
    weakly_referenced = 0
    deallocating = 0
    has_sidetable_rc = 0
    extra_rc = 0
  }
}

isa初始化完毕,再验证

po obj
<LGPerson: 0x10190d0c0>
 x/4gx 0x10190d0c0
0x10190d0c0: 0x001d800100002185 0x0000000000000000
0x10190d0d0: 0x0000000080080000 0x000000010190d371

po 0x001d800100002185 &0x0000000ffffffff8ULL
LGPerson
po 0x001d800100002185
8303516107940229
po 8303516107940229 & 0x0000000ffffffff8ULL
LGPerson

isa获取流程
object_getClass
getIsa
ISA()
(Class)(isa.bits & ISA_MASK)

p (Class)(isa.bits & 0x00007ffffffffff8ULL)
(Class) $3 = LGPerson
上一篇下一篇

猜你喜欢

热点阅读