对象本质是什么?(结构体)怎么证明呢?
首先了解一下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