對(duì)象本質(zhì)是什么助琐?(結(jié)構(gòu)體)怎么證明呢?
首先了解一下clang,Clang是?個(gè)由Apple主導(dǎo)編寫脊凰,基于LLVM的C/C++/Objective-C編譯器
終端執(zhí)行如下命令
clang -rewrite-objc LGPerson.m -o LGPerson.cpp
打開LGPerson.cpp锻梳,可以看到LGPerson被編譯成了一個(gè)結(jié)構(gòu)體箭券,其中有isa指針
struct LGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
};
struct NSObject_IMPL {
Class isa;
};
了解了對(duì)象的本質(zhì)是結(jié)構(gòu)體,那么結(jié)構(gòu)體能被繼承嗎疑枯?通過在xcode中實(shí)際敲代碼發(fā)現(xiàn)報(bào)錯(cuò)所以是不能被繼承的辩块。
但我們可以通過另外一種方式也就是偽繼承的方式實(shí)現(xiàn),如下coding
struct SuperPerson{
int a;
};
struct SonPerson{ //大小等于a 4個(gè)字節(jié) + b 4個(gè)字節(jié) == 8個(gè)字節(jié)
struct SuperPerson ll;
int b;
};
那么如何調(diào)用呢荆永?
struct SuperPerson pp1;
pp1.a = 10;
struct SonPerson pp;
pp.ll.a = 5;
如上所示我們成功的通過SonPerson訪問了SuperPerson的成員
看到了結(jié)構(gòu)體废亭,再多吧啦點(diǎn),結(jié)構(gòu)體大小是怎樣的呢具钥?在內(nèi)存是什么樣子的呢豆村?
NSLog(@"%lu %lu",sizeof(pp1), sizeof(pp));
2020-09-11 15:54:04.309319+0800 KCObjc[21290:479786] 4 8
isa指針會(huì)用到聯(lián)合體,那么什么是聯(lián)合體骂删,與結(jié)構(gòu)體區(qū)別是啥呢掌动?
結(jié)構(gòu)體占用的內(nèi)存大于等于所有成員占用的內(nèi)存的總和(成員之間可能會(huì)存在縫隙)四啰,共用體占用的內(nèi)存等于最長(zhǎng)的成員占用的內(nèi)存。共用體使用了內(nèi)存覆蓋技術(shù)粗恢,同一時(shí)刻只能保存一個(gè)成員的值拟逮,如果對(duì)新的成員賦值,就會(huì)把原來成員的值覆蓋掉适滓。
coding例子如下
union Person{
char eye;
struct{
char eye_colr;
BOOL show_eye;
};
};
調(diào)用如下
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
接下來看看對(duì)象成員isa相關(guān)
通過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是什么?主要用于指針的按位操作,因?yàn)椴荒軐?duì)指針執(zhí)行按位操作敦迄,為了對(duì)指針執(zhí)行按位操作,需要將指針轉(zhuǎn)換為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初始化完畢凭迹,再驗(yàn)證
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