類的探究分析

準(zhǔn)備工作

內(nèi)存偏移

普通指針代碼分析:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
       int a = 10; 
        int b = 10; 
        int *a_p = &a;
        int *b_p = &b;
        NSLog(@"%d -- %p -- %p",a,&a,&a_p);
        NSLog(@"%d -- %p -- %p",b,&b,&b_p);
}

//打印結(jié)果
內(nèi)存偏移[86667:1854956] 10 -- 0x7ffeefbff47c -- 0x7ffeefbff470
內(nèi)存偏移[86667:1854956] 10 -- 0x7ffeefbff478 -- 0x7ffeefbff468
  • 好明顯ab雖然值是一樣的,但是它們的地址卻不一樣蓬衡。這就是我們常說的深拷貝咯掉奄。
  • ab的地址剛好相差了4個(gè)字節(jié)箱歧,這取決于a的的類型。
  • 地址大小比較:a > b > a_p > b_p栓拜,由于是局部變量座泳,他們都存放在棧區(qū)
    注意:棧區(qū)的地址是由高到低的幕与。
    對(duì)象指針代碼分析:
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       XXPerson *p1 = [LGPerson alloc];
        XXPerson *p2 = [LGPerson alloc];
        NSLog(@"%@ -- %p",p1,&p1);
        NSLog(@"%@ -- %p",p2,&p2);

//打印結(jié)果
內(nèi)存偏移[86667:1854957] <LGPerson: 0x100796fb0> -- 0x7ffeefbff460
內(nèi)存偏移[86667:1854957] <LGPerson: 0x10078b730> -- 0x7ffeefbff458
}
  • p1p2的內(nèi)存地址是不一樣的挑势,alloc開辟的內(nèi)存在堆區(qū)
  • &p1&p2的內(nèi)存地址也不一樣的啦鸣,好明顯是指向了兩個(gè)不同的地址潮饱。
    注意:堆區(qū)的地址是由低到高的。
    數(shù)組指針代碼分析:
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int c[4] = {1,2,3,4};
        int *d   = c;
        NSLog(@"%p - %p - %p",&c,&c[0],&c[1]);
        NSLog(@"%p - %p - %p",d,d+1,d+2);

        for (int i = 0; i<4; i++) {
            int value =  *(d+i);
            NSLog(@"%d",value);
        }
}
//打印結(jié)果
內(nèi)存偏移[86667:1854956] 0x7ffeefbff490 - 0x7ffeefbff490 - 0x7ffeefbff494
內(nèi)存偏移[86667:1854956] 0x7ffeefbff490 - 0x7ffeefbff494 - 0x7ffeefbff498
//循環(huán)打印結(jié)果
內(nèi)存偏移[86667:1854956] 1
內(nèi)存偏移[86667:1854956] 2
內(nèi)存偏移[86667:1854956] 3
內(nèi)存偏移[86667:1854956] 4
  • 數(shù)組的地址就是數(shù)組元素內(nèi)存中的首地址诫给,&c,&c[0]指向同一個(gè)地址香拉。
  • 數(shù)組中元素地址的間隔是元素?cái)?shù)據(jù)類型決定的啦扬。
  • 數(shù)組里面的元素可以通過地址+n取址的方式取出來,如*(d+i);
  • 數(shù)組元素不相同用首地址+偏移量方式凫碌,根據(jù)當(dāng)前變量的偏移值(需要前面類型大小相加)
    圖解如下:
    數(shù)組地址偏移

類isa走位的分析

通過之前的文章可以知道對(duì)象本質(zhì)是結(jié)構(gòu)體扑毡,結(jié)構(gòu)體的第一個(gè)成員變量就是isa。那么類的結(jié)構(gòu)是什么有什么证鸥?類有isa指向嘛僚楞?如果有他們之間的關(guān)系是怎么樣的勤晚?那么針對(duì)這些問題我們進(jìn)行以下的分析枉层。

isa的走位圖(官方的)

isa走位圖

iOS不同架構(gòu)下的isa掩碼

  • 拿到類的信息我之前總結(jié)過有三種,用掩碼來獲取是比較快的而且直接的赐写。
  • objc4的源碼可以拿到:
    x86_64:define ISA_MASK 0x00007ffffffffff8ULL
    arm64:define ISA_MASK 0x0000000ffffffff8ULL
    arm64(simulators):define ISA_MASK 0x007ffffffffffff8ULL

類對(duì)象的內(nèi)存?zhèn)€數(shù)

int main(int argc, char * argv[]) {
    @autoreleasepool {
        Class class1 = [MyPersion class];
        Class class2 = [MyPersion alloc].class;
        Class class3 = object_getClass([MyPersion alloc]);
        Class class4 = [MyPersion alloc].class;
        NSLog(@"\n-%p-\n-%p-\n-%p-\n-%p-",class1,class2,class3,class4);  
    }
    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
打印結(jié)果:
2021-06-18 15:57:27.779872+0800 test[1355:490263] 
-0x102e21818-
-0x102e21818-
-0x102e21818-
-0x102e21818-

得出結(jié)論:類的內(nèi)存地址分配都是一樣的鸟蜡,每個(gè)類只有一個(gè)內(nèi)存塊,這根對(duì)象的內(nèi)存分配不一樣挺邀。

對(duì)象的類isa指向(元類的引出)

我自己創(chuàng)建了一個(gè)persion類繼承于NSObject類揉忘,代碼分析如下:

詳細(xì)分析

分析:

  • 0x0000000100ea1a30XXPersion類的地址,當(dāng)我們找出XXPersion類的isa指向的類的地址是0x0000000100ea1a08端铛,也同樣與指向了XXPersion類泣矛。上面已經(jīng)說到了類只會(huì)開辟一個(gè)內(nèi)存空間,那么現(xiàn)在是不是矛盾了禾蚕?還是其中有一個(gè)不是XXpersion類您朽?
  • 其不然,0x0000000100ea1a30輸出的是XXPersion類的地址换淆,0x0000000100ea1a08指向是XXPersion元類哗总。

根元類的引出

參照以上的想法,元類會(huì)不會(huì)也有isa倍试,isa指向是什么讯屈?很簡單,那就實(shí)踐實(shí)踐一下唄县习!請以下操作:

根元類引出

分析:

  • 0x00000001e7afb260地址是XXPersion的元類isa指向的類地址涮母,發(fā)現(xiàn)是NSObject類,然后再找NSObject類的isa指向哪個(gè)類躁愿,發(fā)現(xiàn)地址還是 0x00000001e7afb260叛本,并指向了自己。

總結(jié):

經(jīng)過上面代碼的層層分析攘已,我們驗(yàn)證么isa的走位圖的isa走位流程:objc(對(duì)象) --> class(類) --> metaClass(元類) --> rootMetaClass(根元類) --> rootMetaClass(根元類自己)炮赦。
isa走位圖:

isa走位圖

類的繼承鏈分析

用oc代碼看看繼承鏈的原理,創(chuàng)建XXTeacher類繼承于XXPerson類,如下圖:

繼承鏈代碼

分析:NSObject的父類打印的結(jié)果是nil样勃。XXTeacher的元類的父類是XXPerson的元類(XXPerson的元類的地址和XXPerson類的地址不一樣)吠勘。XXPerson的元類的父類是NSObject的元類性芬,NSObject的元類的父類是NSObject(和NSObject類的地址一樣)

  • XXTeacher 繼承 XXPersonXXPerson 繼承NSObject剧防,NSObject的父類是nil
  • XXTeacher元類 繼承 XXPerson元類植锉,XXPerson 繼承 根元類,根元類繼承NSObject
    類之間的繼承流程圖如下:
    類之間的繼承圖

官方isa走位圖和繼承圖的還原:

還原圖

類的結(jié)構(gòu)分析

查看objc4(818版本)的源碼峭拘,找到了objc_class結(jié)構(gòu)如下:

struct objc_class : objc_object {
  objc_class(const objc_class&) = delete;
  objc_class(objc_class&&) = delete;
  void operator=(const objc_class&) = delete;
  void operator=(objc_class&&) = delete;
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    Class getSuperclass() const {
#if __has_feature(ptrauth_calls)
#   if ISA_SIGNING_AUTH_MODE == ISA_SIGNING_AUTH
        if (superclass == Nil)
            return Nil;

 .........    //源碼位置為objc-runtime-new.h文件第1688行-2173行
//省略了好多代碼

分析

  • 類的結(jié)構(gòu)中也有隱藏的isa俊庇,占用8個(gè)字節(jié)
  • Class superclass是類的父類,占用8個(gè)字節(jié)
  • cache_t cache是類的緩存空間鸡挠,占用16個(gè)字節(jié)
  • class_data_bits_t保存類的數(shù)據(jù)辉饱,如屬性方法等信息拣展。

探究cache_t內(nèi)存大小

我們在開發(fā)過程中看類主要看類的屬性和方法彭沼,上面所述類的屬性和方法都存放在class_data_bits_t結(jié)構(gòu)體中,那么我們必須要知道class_data_bits_t結(jié)構(gòu)體的地址备埃,所以分析cache_t結(jié)構(gòu)體內(nèi)存大小是非常必要的姓惑。上代碼:

struct cache_t {
private:
    explicit_atomic<uintptr_t> _bucketsAndMaybeMask;           //占用8個(gè)字節(jié)
    union {  //聯(lián)合體大小只關(guān)心內(nèi)存最大的成員
        struct {
            explicit_atomic<mask_t>    _maybeMask;   //占用4個(gè)字節(jié)
#if __LP64__
            uint16_t                   _flags;    //占用2個(gè)字節(jié),現(xiàn)在的objc版本只能進(jìn)入這個(gè)判斷
#endif
            uint16_t                   _occupied;     //占用2個(gè)字節(jié)
        };
        explicit_atomic<preopt_cache_t *> _originalPreoptCache;  //占用8個(gè)字節(jié)
    };

#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
    // _bucketsAndMaybeMask is a buckets_t pointer
    // _maybeMask is the buckets mask

    static constexpr uintptr_t bucketsMask = ~0ul;
    static_assert(!CONFIG_USE_PREOPT_CACHES, "preoptimized caches not supported");
   .........忽略與結(jié)構(gòu)體內(nèi)存無關(guān)的代碼
  //源碼位置為objc-runtime-new.h文件第338行-550行

分析:

  • 結(jié)構(gòu)體中static修飾的靜態(tài)變量按脚、調(diào)用的方法已經(jīng)其他相關(guān)的運(yùn)算都不占用結(jié)構(gòu)體的內(nèi)存于毙,所以我省略了好多的代碼。
  • typedef unsigned long uintptr_t是無符號(hào)長整形辅搬,占用8個(gè)字節(jié)唯沮。
  • preopt_cache_t *是結(jié)構(gòu)體指針,占用8個(gè)字節(jié)伞辛。
  • uint16_t是無符號(hào)16位整形烂翰,占用2個(gè)字節(jié)。
  • mask_tuint32_t類型的蚤氏,占用4個(gè)字節(jié)甘耿。
    cache_t的內(nèi)存大小為:uintptr_t內(nèi)存大小8個(gè)字節(jié)+union內(nèi)存大小8個(gè)字節(jié) = 16字節(jié)

分析class_data_bits_t bits結(jié)構(gòu)體

綜上所述,class_data_bits_t bits結(jié)構(gòu)體記錄的是類的屬性竿滨、成員變量以及方法佳恬。所以必須要了解結(jié)構(gòu)體里面有什么哦!上代碼:

struct class_data_bits_t {
    friend objc_class;

    // Values are the FAST_ flags above.
    uintptr_t bits;
private:
    bool getBit(uintptr_t bit) const
    {
        return bits & bit;
    }

    // Atomically set the bits in `set` and clear the bits in `clear`.
    // set and clear must not overlap.
    void setAndClearBits(uintptr_t set, uintptr_t clear)
    {
        ASSERT((set & clear) == 0);
        uintptr_t newBits, oldBits = LoadExclusive(&bits);
      //此處省略部分代碼
public:

    class_rw_t* data() const {
        return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
    void setData(class_rw_t *newData)
    {
   //此處省略部分代碼

class_rw_t結(jié)構(gòu)體

struct class_rw_t {
    // Be warned that Symbolication knows the layout of this structure.
    uint32_t flags;
    uint16_t witness;
#if SUPPORT_INDEXED_ISA
    uint16_t index;
#endif

    explicit_atomic<uintptr_t> ro_or_rw_ext;

    Class firstSubclass;
    Class nextSiblingClass;
//此處省略部分代碼
const method_array_t methods() const {    //獲取方法列表的方法
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->methods;
        } else {
            return method_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseMethods()};
        }
    }

    const property_array_t properties() const {   //獲取屬性的方法
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
        } else {
            return property_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProperties};
        }
    }

    const protocol_array_t protocols() const {         //獲取協(xié)議的方法
        auto v = get_ro_or_rwe();
        if (v.is<class_rw_ext_t *>()) {
            return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->protocols;
        } else {
            return protocol_array_t{v.get<const class_ro_t *>(&ro_or_rw_ext)->baseProtocols};
        }
  //此處省略部分代碼

分析:
是不是很迷茫于游?當(dāng)我們看到那么多代碼時(shí)候該怎么做毁葱?首先我們需要看這個(gè)結(jié)構(gòu)提供了什么方法跟屬性,這是非常重要的7“G憬恕!

  • class_rw_t是結(jié)構(gòu)體類型,提供了獲取屬性列表前痘,方法列表凛捏,協(xié)議列表的方法。通過實(shí)例來驗(yàn)證下方法芹缔,屬性坯癣,變量是不是在class_rw_t中,在XXPerson類中添加屬性和方法 以及成員變量最欠,請繼續(xù)往下看驗(yàn)證流程示罗。

獲取類的屬性、方法操作流程分析

獲取類的屬性

1.創(chuàng)建好XXPersion類芝硬,如圖所示:

XXPerson類

2.斷點(diǎn)蚜点,進(jìn)行l(wèi)ldb調(diào)試,如圖所示:
獲取屬性1

獲取屬性2

步驟:

  • x/4gx XXPerson.class格式化輸出XXPerson.class吵取,拿到類的首地址:0x0000000100004530
  • p/x 0x0000000100004530 + 0x20首地址偏移32個(gè)字節(jié)(ISA8字節(jié)禽额、superclass8字節(jié)、cache16字節(jié))皮官,拿到類對(duì)象屬性地址
  • p (class_data_bits_t *)0x0000000100004550將地址轉(zhuǎn)化成class_data_bits_t類型,為了使用class_data_bits_t的函數(shù)
  • p $21->data() 使用class_data_bits_tdata()函數(shù),拿到class_rw_t類型的地址
  • p $22->properties()通過properties()函數(shù)獲取XXPerson的成員變量
  • p $23.listp $24.ptr解析出property_list_t的地址
  • p *$25 通過取地址的方式獲取成員變量property_list_t
  • p $26.get(0)p $26.get(1)通過c++函數(shù)單個(gè)獲取類的成員變量name实辑、nickName捺氢、age
    注意:
  • 最后獲取屬性的get()方法是迭代器,系統(tǒng)自帶的方法剪撬。
  • 發(fā)現(xiàn)屬性列表中只有3個(gè)摄乒,那么定義的hobby成員變量去哪里了?
  • 方法列表的方法也是同樣獲取的残黑,請接著往下操作馍佑。

獲取類的方法

獲取類方法1

獲取屬性方法2

步驟:NSObject.class -> class_data_bits_t -> class_rw_t -> method_array_t -> method_list_t -> method_t-> big

成員變量與類方法的獲取

成員變量獲取

觀察發(fā)現(xiàn)class_rw_t還有一個(gè)獲取class_ro_t *的方法,會(huì)不會(huì)在class_ro_t中梨水,源碼查看class_ro_t的類型拭荤。

struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif

    union {
        const uint8_t * ivarLayout;
        Class nonMetaclass;
    };

    explicit_atomic<const char *> name;
    // With ptrauth, this is signed if it points to a small list, but
    // may be unsigned if it points to a big list.
    void *baseMethodList;
    protocol_list_t * baseProtocols;
    const ivar_list_t * ivars;              //存儲(chǔ)成員變量

    const uint8_t * weakIvarLayout;
    property_list_t *baseProperties;
//省略了部分代碼(objc-runtime-new.h文件第1037行-1171行)
}

分析:

  • class_ro_t是結(jié)構(gòu)體類型,有一個(gè)ivar_list_t * ivars變量
  • ivar_list_t * ivars變量存儲(chǔ)著類的成員變量疫诽。
  • 系統(tǒng)會(huì)給屬性自動(dòng)生成一個(gè)帶_屬性名變量舅世,存儲(chǔ)在class_ro_t中的變量列表里
    lldb調(diào)試
    類成員變量獲取

    步驟:
  • x/4gx LGPerson.class 格式化輸出LGPerson.class,獲取到首地址
  • p/x 0x100008408 + 0x20 首地址偏移32字節(jié)(ISA8字節(jié)奇徒、superclass8字節(jié)雏亚、cache_t16字節(jié)),拿到包含類屬性方法成員變量的對(duì)象class_data_bits_t的地址
  • p (class_data_bits_t *)$1 將地址轉(zhuǎn)換為class_data_bits_t摩钙,為了使用class_data_bits_t的函數(shù)
  • p $2->data()使用class_data_bits_t的data()函數(shù),拿到class_rw_t類型的地址
  • p $3->ro 使用class_rw_tro函數(shù)罢低,拿到class_ro_t類型的地址
  • p *$4lass_ro_t類型地址的值,拿到了class_ro_t對(duì)象
  • p $5.ivars 使用ivars函數(shù)獲取class_ro_t對(duì)象的ivars,得到了指向ivar_list_t地址的指針
  • p *$6 通過取地址的方式獲實(shí)例變量數(shù)組ivar_list_t,entsize_list_tt<ivar_t, ivar_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 32, count = 4),可以看到有4個(gè)ivars
  • 通過c++函數(shù)get()單個(gè)獲取類的實(shí)例方法:
    p $7.get(0):
    (ivar_t) $8 = {
    offset = 0x0000000100008370
    name = 0x0000000100003eec "hobby"
    type = 0x0000000100003f60 "@"NSString""
    alignment_raw = 3
    size = 8
    }
    ivars獲取流程源碼:NSObject.class -> class_data_bits_t -> class_rw_t -> class_ro_t -> ivar_list_t -> ivar_t

類方法獲取

對(duì)象的方法是存儲(chǔ)在類中胖笛,那么類方法可能存儲(chǔ)在元類中网持。那么實(shí)踐一下咯宜肉。
lldb調(diào)試

類方法獲取

步驟:

  • x/4gx XXPerson.class格式化打印類XXPerson,得到類的首地址
  • p/x 0x00000001000083e0 & 0x00007ffffffffff8isa指針和ISA_MASK做與操作翎碑,拿到XXPerson的metaClass(元類)
  • x/4gx 0x00000001000083e0,格式化打印XXPersonmetaClass(元類)谬返,拿到元類的首地址
  • p/x 0x1000083e0 + 0x20,將元類的首地址偏移32個(gè)字節(jié)(ISA8字節(jié)日杈、superclass8字節(jié)遣铝、cache_t16字節(jié)),那多元類的class_data_bits_t對(duì)象地址
  • p (class_data_bits_t *)0x0000000100008400將地址轉(zhuǎn)化為class_data_bits_t對(duì)象莉擒,方便調(diào)用函數(shù)
  • p $3->data()調(diào)用class_data_bits_tdata函數(shù)酿炸,拿到class_rw_t對(duì)象
  • p $4->methods()獲取class_rw_tmethods方法列表
  • p $5.listp $5.ptr拿到指向method_list_t地址的指針
  • p *$7取地址,拿到了method_list_t對(duì)象,count1涨冀,entsize_list_tt<method_t, method_list_t, 4294901763, method_t::pointer_modifier>= (entsizeAndFlags = 27, count = 1), 有一個(gè)類方法
    通過c++函數(shù)get()big()單個(gè)獲取類的類方法:
    p $7.get(0).big():
    (method_t::big) $9 = {
    name = "sayNB"
    types = 0x0000000100003f74 "v16@0:8"
    imp = 0x0000000100003ce0 (KCObjcBuild+[XXPerson sayNB]) } **類方法獲取流程:NSObject.class->metaClass->class_data_bits_t->class_rw_t->method_array_t->method_list_t->method_t->big`*

總結(jié):

附上類探究的整個(gè)流程圖:

總流程

學(xué)習(xí)過程的確艱辛填硕!但是學(xué)到知識(shí)讓我非常興奮!通過對(duì)類結(jié)構(gòu)的深入學(xué)習(xí)鹿鳖,使得我對(duì)底層的理解更加深刻了扁眯,自身的專業(yè)知識(shí)又有了進(jìn)一步的提升。讓我們繼續(xù)加油吧????翅帜!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姻檀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涝滴,更是在濱河造成了極大的恐慌绣版,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件歼疮,死亡現(xiàn)場離奇詭異杂抽,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)韩脏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門缩麸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骤素,你說我怎么就攤上這事匙睹。” “怎么了济竹?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵痕檬,是天一觀的道長。 經(jīng)常有香客問我送浊,道長梦谜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮唁桩,結(jié)果婚禮上闭树,老公的妹妹穿的比我還像新娘。我一直安慰自己荒澡,他們只是感情好报辱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著单山,像睡著了一般碍现。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上米奸,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天昼接,我揣著相機(jī)與錄音,去河邊找鬼悴晰。 笑死慢睡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铡溪。 我是一名探鬼主播漂辐,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼佃却!你這毒婦竟也來了者吁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤饲帅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后瘤泪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灶泵,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年对途,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赦邻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡实檀,死狀恐怖惶洲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情膳犹,我是刑警寧澤恬吕,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站须床,受9級(jí)特大地震影響铐料,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一钠惩、第九天 我趴在偏房一處隱蔽的房頂上張望柒凉。 院中可真熱鬧,春花似錦篓跛、人聲如沸膝捞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔬咬。三九已至,卻和暖如春央渣,著一層夾襖步出監(jiān)牢的瞬間计盒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工芽丹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留北启,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓拔第,卻偏偏與公主長得像咕村,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚊俺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 今天通過源碼的學(xué)習(xí)對(duì)類進(jìn)行分析懈涛,從isa 的走位和繼承鏈來進(jìn)行展開。我們先來看一下isa經(jīng)典的流程圖: isa流程...
    JEFF009閱讀 292評(píng)論 0 0
  • 前言 上篇博客說完了對(duì)象的成員博客-isa結(jié)構(gòu)分析,今天我們來研究一下對(duì)象的爸爸泳猬,他就是類批钠,相信大家都知道對(duì)象是由...
    羅__閱讀 407評(píng)論 0 1
  • 1、首先拋出問題 類的結(jié)構(gòu)是什么得封? 首先創(chuàng)建一個(gè)LGPesron的類埋心,去cpp文件中。 利用clang編譯成cp...
    瞬間完善閱讀 422評(píng)論 0 2
  • 本文為L_Ares個(gè)人寫作忙上,包括圖片皆為個(gè)人親自操作拷呆,以任何形式轉(zhuǎn)載請表明原文出處。 上一節(jié)[https://ww...
    L_Ares閱讀 494評(píng)論 0 1
  • 忙不是不學(xué)習(xí)的借口 在isa和類的關(guān)聯(lián)[http://www.reibang.com/p/079a6ad90f1...
    丸瘋閱讀 258評(píng)論 0 6