重學(xué)iOS——1.從C角度看OC

面向?qū)ο?/h6>

面向?qū)ο蟮木幊趟季S,簡(jiǎn)而言之就是:一切皆對(duì)象。面向?qū)ο蟮恼Z(yǔ)言區(qū)別于C語(yǔ)言(面向過(guò)程),C語(yǔ)言是按照代碼的執(zhí)行順序去實(shí)現(xiàn)項(xiàng)目功能,而高級(jí)編程語(yǔ)言是從對(duì)象的角度去把控,詳細(xì)解釋就是:任何事件都是由事物構(gòu)成,事物擁有自己特有的屬性(對(duì)象的固有屬性和行為屬性),大事件通過(guò)各種事物之間的相互作用(行為調(diào)用)實(shí)現(xiàn)。OC是從C語(yǔ)言的基礎(chǔ)之上發(fā)展而來(lái)的,是C語(yǔ)言的面向?qū)ο?。OC完全兼容C語(yǔ)言,可以實(shí)現(xiàn)OC與C的混合編程,一起生成可執(zhí)行文件。

OC與C的部分不同點(diǎn)

參考代碼:

#import <Foundation/Foundation.h>
#import <objc/objc.h>

/*
 *要求定義一個(gè)人類
 *事物名稱:人
 *屬性:年齡(age),身高(height),體重(weight)
 *行為:吃飯(eat),睡覺(jué)(sleep),散步(walk)
 */

@interface Person : NSObject
{
    @public
    //屬性
    int _age;
    double _height;
    double _weight;
}
//行為
-(void)eat:(char *)food;

-(void)sleep;

-(void)walk;
+(void)about;
@end


@implementation Person

-(void)eat:(char *)food
{
    NSLog(@"吃%s",food);
}

-(void)walk
{
    NSLog(@"開(kāi)始遛彎");
}

-(void)sleep
{
    NSLog(@"開(kāi)始睡覺(jué)");
}

+(void)about
{
    NSLog("Hello");
}
@end


int main(int argc, const char * argv[]) {
    //1. 通過(guò)類創(chuàng)建對(duì)象
    /*
     *1.開(kāi)辟存儲(chǔ)空間
     *2.初始化所有屬性
     *3.返回指針地址
     */

    //因?yàn)樵诙褩V袆?chuàng)建的對(duì)象,實(shí)質(zhì)是一個(gè)結(jié)構(gòu)體,所以可以通過(guò)結(jié)構(gòu)體指針直接訪問(wèn)屬性
    /*
     *創(chuàng)建對(duì)象的時(shí)候,返回的地址其實(shí)就是類的第0個(gè)屬性的地址
     *結(jié)構(gòu)體創(chuàng)建完成以后,結(jié)構(gòu)體的地址其實(shí)就是結(jié)構(gòu)體第0個(gè)成員的首地址
     *但是需要注意的是:類的第0個(gè)屬性并不是我們編寫的_age,而是一個(gè)叫做isa的屬性
     *isa是一個(gè)指針,占8個(gè)字節(jié)
     *
     *其實(shí)類也是一個(gè)對(duì)象,也就意味著Person也是一個(gè)對(duì)象
     *平時(shí)我們所說(shuō)的創(chuàng)建對(duì)象,就是通過(guò)一個(gè)類對(duì)象創(chuàng)建一個(gè)新的對(duì)象
     *類對(duì)象是系統(tǒng)自動(dòng)幫我們創(chuàng)建的,里面保存了當(dāng)前對(duì)象的所有方法,準(zhǔn)確說(shuō)是一個(gè)方法列表,包括方法體
     *而實(shí)際對(duì)象是程序自己?jiǎn)T手動(dòng)通過(guò)new來(lái)創(chuàng)建的,而實(shí)例對(duì)象中有一個(gè)isa指針就指向了創(chuàng)建它的那個(gè)類對(duì)象
     */
    Person *p=[Person new];
    p->_age=30;
    p->_height=1.75;
    p->_weight=65.0;
    [p walk];
    [Person about];
    NSLog(@"p=%p",p);
    NSLog(@"&age=%p",&(p->_age));
    /*
     *結(jié)構(gòu)體創(chuàng)建完成以后,結(jié)構(gòu)體的地址其實(shí)就是結(jié)構(gòu)體第0個(gè)成員的首地址
     */
    //    struct Person
    //    {
    //        int age;
    //        char *name;
//    };
//    struct Person sp;
//    NSLog(@"&sp=%p",&sp);
//    NSLog(@"&age=%p",&sp.age);
    return 0;
}

1.#import和#include的區(qū)別
import的功能和include的功能是一樣的,都是導(dǎo)入文件,但是OC為了避免C語(yǔ)言中的重復(fù)導(dǎo)入問(wèn)題(避免使用復(fù)雜的頭文件衛(wèi)士)為import集成了避免重復(fù)導(dǎo)入的機(jī)制。下面介紹一下C語(yǔ)言中頭文件衛(wèi)士的寫法:

#ifndef _TEST_H
#define _TEST_H//一般是文件名的大寫
頭文件結(jié)尾寫上一行:
#endif

這樣一個(gè)工程文件里同時(shí)包含兩個(gè)test.h時(shí),就不會(huì)出現(xiàn)重定義的錯(cuò)誤了。
分析:當(dāng)?shù)谝淮伟瑃est.h時(shí),由于沒(méi)有定義_TEST_H,條件為真,這樣就會(huì)包含(執(zhí)行)#ifndef _TEST_H和#endif之間的代碼,當(dāng)?shù)诙伟瑃est.h時(shí)前面一次已經(jīng)定義了_TEST_H,條件為假,#ifndef _TEST_H和#endif之間的代碼也就不會(huì)再次被包含,這樣就避免了重定義了。
當(dāng)然以上這些內(nèi)容都是關(guān)于C語(yǔ)言-預(yù)處理的知識(shí)內(nèi)容,具體細(xì)節(jié)參考:C語(yǔ)言再學(xué)習(xí)——C預(yù)處理器和頭文件為什么要加#ifndef #define #endif

2.OC實(shí)現(xiàn)面向?qū)ο蟮脑?br> OC是對(duì)C語(yǔ)言進(jìn)行了面向?qū)ο蟮姆庋b,即通過(guò)C語(yǔ)言實(shí)現(xiàn)面向?qū)ο螅敲词侨绾螌?shí)現(xiàn)的?其實(shí)是結(jié)構(gòu)體+指針的方式實(shí)現(xiàn)的。OC中的對(duì)象在內(nèi)存中其實(shí)是以結(jié)構(gòu)體的形式進(jìn)行存儲(chǔ)的。這一點(diǎn)的內(nèi)容就涉及到了runtime運(yùn)行時(shí)的內(nèi)容。在這里由于目前還沒(méi)有涉及到運(yùn)行時(shí)內(nèi)容,所以對(duì)本部分內(nèi)容進(jìn)行了適當(dāng)?shù)暮?jiǎn)化,同時(shí)也增進(jìn)了后期運(yùn)行時(shí)內(nèi)容的進(jìn)一步學(xué)習(xí)與理解。
OC中的對(duì)象是通過(guò)結(jié)構(gòu)體來(lái)實(shí)現(xiàn)的,即在堆中對(duì)象的存儲(chǔ)數(shù)據(jù)結(jié)構(gòu)是struct,創(chuàng)建的對(duì)象變量,其實(shí)是一個(gè)指向相應(yīng)類結(jié)構(gòu)體的指針。由于對(duì)象的實(shí)際結(jié)構(gòu)是結(jié)構(gòu)體,那么我們可以通過(guò)"->”這樣的方式去訪問(wèn)實(shí)例對(duì)象中的屬性,代碼如下:

IPhone *p=[IPhone new];
p->_color=0;//默認(rèn)@interface中的屬性都是@protected的,如果想這樣子直接訪問(wèn),需要使用@public
p->_model=0;

在實(shí)際的實(shí)例對(duì)象存儲(chǔ)過(guò)程中,實(shí)例對(duì)象內(nèi)部是不存在實(shí)例方法的,只包含屬性信息和isa指針信息,isa指針指向該類的類對(duì)象,類對(duì)象是在程序編譯階段,系統(tǒng)自動(dòng)創(chuàng)建的,包含了類的所有信息(屬性列表、方法列表、類名等信息),是創(chuàng)建實(shí)例對(duì)象的依據(jù)(模板)。需要注意的是:結(jié)構(gòu)體創(chuàng)建完成以后,結(jié)構(gòu)體的地址其實(shí)就是結(jié)構(gòu)體第0個(gè)成員的首地址,但是類對(duì)象的首地址是isa指針屬性的存儲(chǔ)值,isa是一個(gè)指針,占8位。具體在內(nèi)存中的存在方式如下圖所示:

對(duì)象創(chuàng)建過(guò)程.png

所以從上圖中我們可以聯(lián)想到,[Person new]方法,其實(shí)是調(diào)用了Person類對(duì)象的new方法。參考代碼中的[p walk]和 [Person about]對(duì)比會(huì)發(fā)現(xiàn),類方法的執(zhí)行效率高于實(shí)例方法。圖解如下:

[p walk]分析.png
[Person about]分析.png

兩幅圖的分析,故意將元類的概念略去,因?yàn)轭惙椒▽?shí)際是存儲(chǔ)在元類中的,但是在此為了方便理解,同時(shí)也為后期進(jìn)階做準(zhǔn)備。
上圖中涉及到了堆、棧、代碼區(qū)等內(nèi)容,具體可以參考iOS中的內(nèi)存管理C語(yǔ)言中內(nèi)存分配linux內(nèi)存管理深入淺出-iOS內(nèi)存分配與分區(qū)

3.OC中的類方法和實(shí)例方法以及函數(shù)
OC和C中的函數(shù)的對(duì)比,其實(shí)很簡(jiǎn)單,在這里直接上代碼,我覺(jué)得對(duì)于身為程序員的自己來(lái)說(shuō),可能會(huì)更加清晰,注意點(diǎn):在Java中對(duì)象可以直接調(diào)用類方法,但是在OC中對(duì)象不能調(diào)用類方法,必須通過(guò)類調(diào)用類方法。靜態(tài)方法、類方法和對(duì)象方法的區(qū)別

//
//  main.m
//  OC_day1_04_類方法
//
//  Created by 劉旭輝 on 2017/10/13.
//  Copyright ? 2017年 劉旭輝. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef enum
{
    KIColorBlace,//黑色
    KIColorWhite,//白色
    KIColorTuHaoJin//土豪金
}IColor;
//1.編寫類的聲明
@interface IPhone : NSObject
{
@public
    double _size;
//    int _color; //顏色 0代表黑色 1代表白色 2代表土豪金
    int _cpu;
    int _model;
    IColor _color;
}
/*
 *行為
 *OC中的行為和C語(yǔ)言中的函數(shù)一樣,都是用來(lái)保存一段特定功能的代碼
 *OC中定義一個(gè)方法,也分為聲明和實(shí)現(xiàn),聲明在@interface中,實(shí)現(xiàn)寫在@implementation
 *
 *C語(yǔ)言中的函數(shù)分為兩種:內(nèi)部函數(shù)和外部函數(shù)
 *OC中的函數(shù)也分為兩種:類方法和對(duì)象方法
 *類方法只能用類名調(diào)用,對(duì)象方法只能用對(duì)象調(diào)用
 *OC中的類方法用+表示,OC中的對(duì)象方法用-表示
 *
 *編寫C語(yǔ)言函數(shù)的規(guī)律:1.確定函數(shù)名稱;2.確定形參;3.確定返回值;4.確定返回值類型
 *編寫OC方法也有規(guī)律,規(guī)律和C語(yǔ)言一模一樣
 */

/*C語(yǔ)言方法
 void about();
 void about()
 {
     printf("model=cpu=size=color");
 }
 */

//注意:OC中的方法,如果沒(méi)有形參不需要寫(),而是直接寫一個(gè);
//為什么OC中沒(méi)有形參不需要寫()呢?因?yàn)镺C方法中的()有特殊用途,OC方法中的()是用來(lái)括住數(shù)據(jù)類型的
//行為的聲明
-(void)about;

/*
 *C語(yǔ)言中的函數(shù):1.沒(méi)有返回值沒(méi)有參數(shù)的函數(shù);2.有返回值沒(méi)有參數(shù)的;3.有返回值有參數(shù)的;4.沒(méi)有返回值有參數(shù)的
 *OC中的方法也有四種
 */

//有返回值沒(méi)有參數(shù)的。例如:讀取短信
-(char *)loadMessage;

//有返回值有參數(shù)的,例如:打電話
//int signal(int number); C語(yǔ)言中的函數(shù)
//注意:OC中的方法如果有參數(shù),那么每個(gè)參數(shù)的數(shù)據(jù)類型前面必須加一個(gè):
//注意:當(dāng)前的有參數(shù)的方法的方法名稱是  signal: 冒號(hào)也是方法名稱的一部分
-(int)signal:(int)number;

//有返回值,并且有多個(gè)參數(shù)的,發(fā)短信
//int sendMessage(int number,char* content);
//為了提高閱讀性,OC方法允許我們給每一個(gè)參數(shù)添加一個(gè)標(biāo)簽來(lái)說(shuō)明當(dāng)前參數(shù)的含義
-(int)sendMessageWithNumber:(int)number andContent:(char*) content;
//-(int)sendMessage:(int)number :(char*) content; //當(dāng)前的方法名稱叫做:sendMessage::

//沒(méi)有返回值,有參數(shù)的函數(shù)
-(void)callWithNumber:(int) number;


//計(jì)算器功能(類方法)
//如果你不想每次使用方法都需要?jiǎng)?chuàng)建對(duì)象并且開(kāi)辟存儲(chǔ)空間
//并且如果該方法中沒(méi)有使用到屬性(成員變量),那么你可以把這個(gè)方法定義為類方法
//對(duì)象方法用對(duì)象調(diào)用 類方法用類名調(diào)用
//-(int)sumWithNumber1:(int)number1 andNumber2:(int) number2;
//只需要將對(duì)象方法的-號(hào)轉(zhuǎn)換成+,那么就定義了一個(gè)類方法
//注意:如果實(shí)現(xiàn)了一個(gè)類方法,就必須去實(shí)現(xiàn)類方法
//如果實(shí)現(xiàn)的是一個(gè)對(duì)象方法,那么就必須去實(shí)現(xiàn)對(duì)象方法




/*
 *類方法和對(duì)象方法的區(qū)別
 *0.對(duì)象方法以-開(kāi)頭;類方法以+開(kāi)頭
 *1.對(duì)象方法必須用對(duì)象調(diào)用,類方法必須用類調(diào)用
 *2.對(duì)象方法中可以直接訪問(wèn)屬性(成員變量),類方法中不可以直接訪問(wèn)屬性(成員變量)
 *3.類方法的優(yōu)點(diǎn),調(diào)用類方法的效率會(huì)比調(diào)用對(duì)象方法高
 *4.類方法和對(duì)象方法可以進(jìn)行相互調(diào)用
 *4.1對(duì)象方法中可以直接調(diào)用類方法
 *4.2可以在類方法中間接調(diào)用對(duì)象方法
 *4.3在類方法中可以直接調(diào)用其他方法
 *4.4對(duì)象方法中可以直接調(diào)用對(duì)象方法
 */


/*
 *類方法的應(yīng)用場(chǎng)景
 *如果方法中沒(méi)有使用到屬性(成員變量),那么能用類方法就用類方法
 *類方法的執(zhí)行效率比對(duì)象方法高
 *
 *類方法一般用于定義工具方法
 *字符串查找
 *文件操作
 *數(shù)據(jù)庫(kù)操作
 */
+(int)sumWithNumber1:(int)number1 andNumber2:(int) number2;
@end

//2.編寫類的實(shí)現(xiàn)
@implementation IPhone
//行為的實(shí)現(xiàn)
-(void)about
{
    //    NSLog(@"打印本機(jī)信息");
    //如果在對(duì)象方法中想訪問(wèn)該對(duì)象的屬性,可以直接寫上_屬性名稱即可
    [IPhone sumWithNumber1:50 andNumber2:50];
    NSLog(@"size=%f,color=%i,model=%i,cpu=%i",_size,_color,_model,_cpu);
}

-(char *)loadMessage
{
      return "老婆我們家我做主";
 }

-(int)signal:(int)number
{
    NSLog(@"打電話給%i",number);
    return 1;
}

-(int)sendMessage:(int)number :(char *)content
{
    NSLog(@"發(fā)短信給%i,內(nèi)容是%s",number,content);
    return 0;
}

-(int)sendMessageWithNumber:(int)number andContent:(char *)content
{
    NSLog(@"發(fā)短信給%i,內(nèi)容是%s",number,content);
    return 0;
}
-(void)callWithNumber:(int)number
{
    NSLog(@"打電話給%i",number);
}

+(int)sumWithNumber1:(int)number1 andNumber2:(int)number2
{
    IPhone *p1=[IPhone new];
    [p1 about];//在類方法中,可以簡(jiǎn)介調(diào)用對(duì)象方法,但是在企業(yè)開(kāi)發(fā)中,不建議這樣子使用
    return number1+number2;
}

@end
int main(int argc, const char * argv[]) {
    //1.通過(guò)類創(chuàng)建對(duì)象
    IPhone *p=[IPhone new];
    p->_color=KIColorBlace;
    p->_model=4;
    p->_cpu=1;
    p->_size=3.5;
    //3.獲取對(duì)象的屬性
    //    NSLog(@"size=%f,color=%i,model=%i,cpu=%i",p->_size,p->_color,p->_model,p->_cpu);
    //4.如果給對(duì)象發(fā)消息(如果調(diào)用對(duì)象的方法)
    [p about];
    //注意:OC中的NSLog對(duì)C語(yǔ)言中的字符串支持不是很好,如果返回的是中文的C語(yǔ)言字符串可能輸出是亂碼,也可能什么都不輸出
    NSLog(@"%s",[p loadMessage]);
    [IPhone sumWithNumber1:1 andNumber2:2];
    //    [p sendMessage:110 :"help,help"];
    [p sendMessageWithNumber:110 andContent:"help"];
    [p sendMessage:110 :"help,help"];
    [p signal:110];
    [p callWithNumber:119];
    return 0;
}

void test()
{
    //1.創(chuàng)建一個(gè)對(duì)象
    IPhone *p1=[IPhone new];
    //2.利用對(duì)象調(diào)用假發(fā)運(yùn)算方法
//    [p1 sumWithNumber1:1 andNumber2:2];
}

4.OC成員變量、局部變量、全局變量的區(qū)別以及內(nèi)存分析

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    //寫在類聲明的大括號(hào)中的變量,我們稱之為成員變量(或者屬性,實(shí)例變量)
    //注意:
    //1.成員變量不能離開(kāi)類,離開(kāi)類以后就不是成員變量;
    //2.成員變量不能在定義的同時(shí)進(jìn)行初始化;
    //3.成員變量只能通過(guò)對(duì)象來(lái)訪問(wèn)
    //存儲(chǔ)在:堆(當(dāng)前對(duì)應(yīng)的堆的內(nèi)存空間中)
    //存儲(chǔ)在堆中的數(shù)據(jù),不會(huì)被自動(dòng)釋放,只能程序員手動(dòng)釋放
    int age;
}

@end

@implementation Person



@end
//寫在函數(shù)和大括號(hào)外部的變量,我們稱之為全局變量
//作用域:從定義的那一行開(kāi)始,一直到文件末尾
//全局變量可以先定義再初始化,也可以定義的同時(shí)初始化
//存儲(chǔ)在:靜態(tài)區(qū)
//程序一啟動(dòng)就會(huì)分配內(nèi)存空間,知道程序結(jié)束才會(huì)釋放
int a;
int b=10;
int main(int argc, const char * argv[]) {
    //寫在函數(shù)或者代碼塊中的變量,我們稱之為局部變量
    //作用域:從定義的哪一行開(kāi)始,一直到遇到大括號(hào)或者return
    //局部變量可以先定義再初始化,也可以定義的同時(shí)初始化
    //存儲(chǔ)在棧中
    //存儲(chǔ)在棧中的數(shù)據(jù)有一個(gè)特點(diǎn),系統(tǒng)會(huì)自動(dòng)給我們釋放
    int num=10;
    return 0;
}
#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    //寫在類聲明的大括號(hào)中的變量,我們稱之為成員變量(或者屬性,實(shí)例變量)
    //注意:
    //1.成員變量不能離開(kāi)類,離開(kāi)類以后就不是成員變量;
    //2.成員變量不能在定義的同時(shí)進(jìn)行初始化;
    //3.成員變量只能通過(guò)對(duì)象來(lái)訪問(wèn)
    //存儲(chǔ)在:堆(當(dāng)前對(duì)應(yīng)的堆的內(nèi)存空間中)
    //存儲(chǔ)在堆中的數(shù)據(jù),不會(huì)被自動(dòng)釋放,只能程序員手動(dòng)釋放
    int age;
}

@end

@implementation Person



@end
//寫在函數(shù)和大括號(hào)外部的變量,我們稱之為全局變量
//作用域:從定義的那一行開(kāi)始,一直到文件末尾
//全局變量可以先定義再初始化,也可以定義的同時(shí)初始化
//存儲(chǔ)在:靜態(tài)區(qū)
//程序一啟動(dòng)就會(huì)分配內(nèi)存空間,知道程序結(jié)束才會(huì)釋放
int a;
int b=10;
int main(int argc, const char * argv[]) {
    //寫在函數(shù)或者代碼塊中的變量,我們稱之為局部變量
    //作用域:從定義的哪一行開(kāi)始,一直到遇到大括號(hào)或者return
    //局部變量可以先定義再初始化,也可以定義的同時(shí)初始化
    //存儲(chǔ)在棧中
    //存儲(chǔ)在棧中的數(shù)據(jù)有一個(gè)特點(diǎn),系統(tǒng)會(huì)自動(dòng)給我們釋放
    int num=10;
    return 0;
}

在以上的代碼中已經(jīng)對(duì)成員變量、全局變量、局部變量做了詳細(xì)的區(qū)分,但是在內(nèi)存中具體是如何存儲(chǔ)的?還沒(méi)有一個(gè)明確的概念。通過(guò)閱讀一些博客,對(duì)物理存儲(chǔ)有了一定的了解,分析如下:

  • RAM和ROM區(qū)分
    我們所說(shuō)的內(nèi)存,其實(shí)指的就是RAM,在程序運(yùn)行期間系統(tǒng)將ROM中的源代碼加載到RAM中,我們所說(shuō)的棧、堆、全局區(qū)/靜態(tài)區(qū)、常量區(qū)、代碼區(qū)其實(shí)都是位于RAM中。

    RAM:運(yùn)行內(nèi)存,不能掉電存儲(chǔ)。
    ROM:存儲(chǔ)性內(nèi)存,可以掉電存儲(chǔ),例如內(nèi)存卡、Flash。
    由于RAM類型不具備掉電存儲(chǔ)能力(即一掉電數(shù)據(jù)消失),所以app程序一般存放于ROM中。RAM的訪問(wèn)速度要遠(yuǎn)高于ROM,價(jià)格也要高。App程序啟動(dòng),系統(tǒng)會(huì)把開(kāi)啟的那個(gè)App程序從Flash或ROM里面拷貝到內(nèi)存(RAM),然后從內(nèi)存里面執(zhí)行代碼。另一個(gè)原因是CPU不能直接從內(nèi)存卡里面讀取指令(需要Flash驅(qū)動(dòng)等等)。

  • RAM中五大分區(qū)詳解

  1. 棧區(qū)(stack):
    存放的局部變量、先進(jìn)后出、一旦出了作用域就會(huì)被銷毀;函數(shù)跳轉(zhuǎn)地址,現(xiàn)場(chǎng)保護(hù)等;
    程序猿不需要管理?xiàng)^(qū)變量的內(nèi)存。主要負(fù)責(zé)函數(shù)模塊內(nèi)申請(qǐng),函數(shù)結(jié)束時(shí)自動(dòng)釋放,存放局部變量,函數(shù)變量
    ~棧區(qū)地址從高到低分配;
  2. 堆區(qū)(heap):
    通過(guò)malloc函數(shù)或new函數(shù)等操作符操作的得到,需要程序員自己管理
    ARC的內(nèi)存的管理,是編譯器再便宜的時(shí)候自動(dòng)添加 retain、release、autorelease;
    ~堆區(qū)的地址是從低到高分配
  3. 全局區(qū)/靜態(tài)區(qū)(static):
    包括兩個(gè)部分:未初始化過(guò)(.bss段區(qū)域) 、初始化過(guò)(data段區(qū)域),即全局區(qū)/靜態(tài)區(qū)在內(nèi)存中是放在一起的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域。
  4. 常量區(qū):存放常量字符串;
  5. 代碼區(qū): 存放編寫的源代碼,由系統(tǒng)自動(dòng)加載進(jìn)入;
  6. 注意:也有人將全局區(qū)/靜態(tài)區(qū)(static)和常量區(qū)聯(lián)合在一起成為數(shù)據(jù)區(qū)。

具體圖示如下圖所示:

內(nèi)存分區(qū)圖解

5.函數(shù)與方法的區(qū)別
首先需要理解的一點(diǎn)是:方法是對(duì)象的行為,函數(shù)是整個(gè)文件的一個(gè)功能塊。方法只能存在于類內(nèi)部,函數(shù)可以存在于整個(gè)文件的任何地方。具體代碼如下:

#import <Foundation/Foundation.h>


/*
 *函數(shù)和方法的區(qū)別
 *1.函數(shù)屬于整個(gè)文件,方法屬于某一個(gè)類,方法如果離開(kāi)類就不行
 *2.函數(shù)可以直接調(diào)用,方法必須用對(duì)象或者類來(lái)調(diào)用
 *注意:雖然函數(shù)屬于整個(gè)文件,但是如果把函數(shù)寫在類的聲明中就會(huì)不識(shí)別
 *3.不能把函數(shù)當(dāng)做方法調(diào)用,也不能將方法當(dāng)做函數(shù)調(diào)用
 *
 *
 *方法的注意點(diǎn):
 *方法可以只有聲明沒(méi)有實(shí)現(xiàn),也可以只有實(shí)現(xiàn)沒(méi)有聲明,編譯不會(huì)報(bào)錯(cuò),但是運(yùn)行會(huì)報(bào)錯(cuò)
 *如果方法只有聲明而沒(méi)有實(shí)現(xiàn),則會(huì)報(bào)錯(cuò):1.reason:'+[Person demo]:unrecognized selector sent to class 0x100001140',發(fā)送了一個(gè)不能識(shí)別的消息,在Person類中沒(méi)有+開(kāi)頭的方法
 *reason:'-[Person test]:unrecognized selector sent to instance 0x100001140'
 *類也可以只有實(shí)現(xiàn)沒(méi)有聲明,例如:@implementation Person : NSObjec ... @end
 */

@interface Person : NSObject
//對(duì)象方法的聲明
-(void)test;
//類方法聲明
+(void)demo;
@end

@implementation Person
//對(duì)象方法的實(shí)現(xiàn)
-(void)test
{
    NSLog(@"test");
}
//類方法的實(shí)現(xiàn)
+(void)demo
{
    NSLog(@"demo");
}

@end
//外部函數(shù)的聲明
extern void sum();
//內(nèi)部函數(shù)的聲明
static void minus();
//外部函數(shù)
extern void sum()
{
    printf("sum");
}
//內(nèi)部函數(shù)
static void minus()
{
    printf("minus");
}

int main(int argc, const char * argv[]) {
    
    return 0;
}

6.結(jié)構(gòu)體作為對(duì)象屬性的細(xì)節(jié)
當(dāng)結(jié)構(gòu)體作為函數(shù)(C語(yǔ)言中的稱呼)參數(shù)或者作為對(duì)象屬性的情況下,結(jié)構(gòu)體是以拷貝結(jié)構(gòu)體屬性的方式進(jìn)行傳遞的,此過(guò)程傳遞的不是指針。
結(jié)構(gòu)體作為屬性的代碼示例:
類模型

#import <Foundation/Foundation.h>

/*
 *合理的設(shè)計(jì)一個(gè)“學(xué)生”類
 *學(xué)生有*姓名*生日另個(gè)屬性和說(shuō)出自己姓名生日的方法
 *要求利用設(shè)計(jì)的學(xué)生類創(chuàng)建學(xué)生對(duì)象,并且說(shuō)出自己的姓名和年齡
 */

//定義一個(gè)新類型Date
typedef struct
{
    int year;
    int month;
    int day;
}Date;

@interface Student : NSObject
{
    @public
    NSString *_name;
    
    Date _birthday;
}
-(void)say;
@end

@implementation Student

-(void)say
{
    NSLog(@"name=%@;year=%i,month=%i,day=%i",_name,_birthday.year,_birthday.month,_birthday.day);
}

@end

結(jié)構(gòu)體屬性修改范例

int main(int argc, const char * argv[]) {
    //1.創(chuàng)建學(xué)生對(duì)象
    Student *student=[Student new];
    [student say];
    //2.設(shè)置學(xué)生對(duì)象的屬性
    student->_name=@"lxh";
    /*
     *student->_birthday={1992,12,23};錯(cuò)誤原因
     *1.結(jié)構(gòu)體只能在定義的時(shí)候初始化
     *2.系統(tǒng)并不清楚它({1992,12,23})是數(shù)組還是結(jié)構(gòu)體
     */
    student->_birthday=(Date){1992,12,23};
    //student->_birthday=(Date){1992,12,23};這句話的本質(zhì)其實(shí)是:結(jié)構(gòu)體拷貝,將結(jié)構(gòu)體{1992,12,23}強(qiáng)制拷貝給了_birthday
    /*
    Date d1={1999,1,5};
    Date d2;
    d2=d1; //當(dāng)結(jié)構(gòu)體作為函數(shù)的參數(shù)的時(shí)候,賦值其實(shí)是將結(jié)構(gòu)體內(nèi)部的屬性,進(jìn)行了一次拷貝
           //這里是將d1內(nèi)部的屬性都拷貝了一份賦值給了d2
    d2.year=2000;//修改d2的值并不影響d1的值
    printf("d1=year=%i\n",d1.year);
    printf("d2=year=%i\n",d2.year);
    */
    
    /*
     *這種方式賦值也可以,單個(gè)賦值
     */
    student->_birthday.year=1992;
    student->_birthday.month=12;
    student->_birthday.day=23;
    
    /*
     *第三種賦值方式
     */
    Date d={1992,12,23};
    student->_birthday=d;
    return 0;
}

歡迎關(guān)注我的個(gè)人微信公眾號(hào),免費(fèi)送計(jì)算機(jī)各種最新視頻資源!你想象不到的精彩!


0.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容