面向?qū)ο?/h6>
面向?qū)ο蟮木幊趟季S壁晒,簡而言之就是:一切皆對象秒咐。面向?qū)ο蟮恼Z言區(qū)別于C語言(面向過程)携取,C語言是按照代碼的執(zhí)行順序去實(shí)現(xiàn)項(xiàng)目功能雷滋,而高級編程語言是從對象的角度去把控文兢,詳細(xì)解釋就是:任何事件都是由事物構(gòu)成姆坚,事物擁有自己特有的屬性(對象的固有屬性和行為屬性),大事件通過各種事物之間的相互作用(行為調(diào)用)實(shí)現(xiàn)兔辅。OC是從C語言的基礎(chǔ)之上發(fā)展而來的维苔,是C語言的面向?qū)ο蠼槭薄C完全兼容C語言潮尝,可以實(shí)現(xiàn)OC與C的混合編程饿序,一起生成可執(zhí)行文件原探。
OC與C的部分不同點(diǎn)
參考代碼:
#import <Foundation/Foundation.h>
#import <objc/objc.h>
/*
*要求定義一個人類
*事物名稱:人
*屬性:年齡(age),身高(height)咽弦,體重(weight)
*行為:吃飯(eat),睡覺(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(@"開始遛彎");
}
-(void)sleep
{
NSLog(@"開始睡覺");
}
+(void)about
{
NSLog("Hello");
}
@end
int main(int argc, const char * argv[]) {
//1. 通過類創(chuàng)建對象
/*
*1.開辟存儲空間
*2.初始化所有屬性
*3.返回指針地址
*/
//因?yàn)樵诙褩V袆?chuàng)建的對象段审,實(shí)質(zhì)是一個結(jié)構(gòu)體闹蒜,所以可以通過結(jié)構(gòu)體指針直接訪問屬性
/*
*創(chuàng)建對象的時候绷落,返回的地址其實(shí)就是類的第0個屬性的地址
*結(jié)構(gòu)體創(chuàng)建完成以后,結(jié)構(gòu)體的地址其實(shí)就是結(jié)構(gòu)體第0個成員的首地址
*但是需要注意的是:類的第0個屬性并不是我們編寫的_age筐喳,而是一個叫做isa的屬性
*isa是一個指針避归,占8個字節(jié)
*
*其實(shí)類也是一個對象梳毙,也就意味著Person也是一個對象
*平時我們所說的創(chuàng)建對象顿天,就是通過一個類對象創(chuàng)建一個新的對象
*類對象是系統(tǒng)自動幫我們創(chuàng)建的蔑担,里面保存了當(dāng)前對象的所有方法啤握,準(zhǔn)確說是一個方法列表排抬,包括方法體
*而實(shí)際對象是程序自己員手動通過new來創(chuàng)建的,而實(shí)例對象中有一個isa指針就指向了創(chuàng)建它的那個類對象
*/
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個成員的首地址
*/
// 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語言中的重復(fù)導(dǎo)入問題(避免使用復(fù)雜的頭文件衛(wèi)士)為import集成了避免重復(fù)導(dǎo)入的機(jī)制漱抓。下面介紹一下C語言中頭文件衛(wèi)士的寫法:
#ifndef _TEST_H
#define _TEST_H//一般是文件名的大寫
頭文件結(jié)尾寫上一行:
#endif
這樣一個工程文件里同時包含兩個test.h時乞娄,就不會出現(xiàn)重定義的錯誤了仪或。
分析:當(dāng)?shù)谝淮伟瑃est.h時追迟,由于沒有定義_TEST_H敦间,條件為真,這樣就會包含(執(zhí)行)#ifndef _TEST_H和#endif之間的代碼厢绝,當(dāng)?shù)诙伟瑃est.h時前面一次已經(jīng)定義了_TEST_H昔汉,條件為假靶病,#ifndef _TEST_H和#endif之間的代碼也就不會再次被包含口予,這樣就避免了重定義了沪停。
當(dāng)然以上這些內(nèi)容都是關(guān)于C語言-預(yù)處理的知識內(nèi)容木张,具體細(xì)節(jié)參考:C語言再學(xué)習(xí)——C預(yù)處理器和頭文件為什么要加#ifndef #define #endif
2.OC實(shí)現(xiàn)面向?qū)ο蟮脑?br>
OC是對C語言進(jìn)行了面向?qū)ο蟮姆庋b,即通過C語言實(shí)現(xiàn)面向?qū)ο缶槌梗敲词侨绾螌?shí)現(xiàn)的蛛株?其實(shí)是結(jié)構(gòu)體+指針的方式實(shí)現(xiàn)的。OC中的對象在內(nèi)存中其實(shí)是以結(jié)構(gòu)體的形式進(jìn)行存儲的。這一點(diǎn)的內(nèi)容就涉及到了runtime運(yùn)行時的內(nèi)容屉符。在這里由于目前還沒有涉及到運(yùn)行時內(nèi)容锹引,所以對本部分內(nèi)容進(jìn)行了適當(dāng)?shù)暮喕颖洌瑫r也增進(jìn)了后期運(yùn)行時內(nèi)容的進(jìn)一步學(xué)習(xí)與理解。
OC中的對象是通過結(jié)構(gòu)體來實(shí)現(xiàn)的东涡,即在堆中對象的存儲數(shù)據(jù)結(jié)構(gòu)是struct疮跑,創(chuàng)建的對象變量祖娘,其實(shí)是一個指向相應(yīng)類結(jié)構(gòu)體的指針啊奄。由于對象的實(shí)際結(jié)構(gòu)是結(jié)構(gòu)體菇夸,那么我們可以通過"->”這樣的方式去訪問實(shí)例對象中的屬性峻仇,代碼如下:
IPhone *p=[IPhone new];
p->_color=0;//默認(rèn)@interface中的屬性都是@protected的,如果想這樣子直接訪問凡蚜,需要使用@public
p->_model=0;
在實(shí)際的實(shí)例對象存儲過程中朝蜘,實(shí)例對象內(nèi)部是不存在實(shí)例方法的谱醇,只包含屬性信息和isa指針信息,isa指針指向該類的類對象奈附,類對象是在程序編譯階段煮剧,系統(tǒng)自動創(chuàng)建的勉盅,包含了類的所有信息(屬性列表、方法列表挑胸、類名等信息)茬贵,是創(chuàng)建實(shí)例對象的依據(jù)(模板)闷沥。需要注意的是:結(jié)構(gòu)體創(chuàng)建完成以后咐容,結(jié)構(gòu)體的地址其實(shí)就是結(jié)構(gòu)體第0個成員的首地址戳粒,但是類對象的首地址是isa指針屬性的存儲值,isa是一個指針奄妨,占8位苹祟。具體在內(nèi)存中的存在方式如下圖所示:
所以從上圖中我們可以聯(lián)想到砸抛,[Person new]方法树枫,其實(shí)是調(diào)用了Person類對象的new方法。參考代碼中的[p walk]和 [Person about]對比會發(fā)現(xiàn)奔誓,類方法的執(zhí)行效率高于實(shí)例方法厨喂。圖解如下:
兩幅圖的分析蜕煌,故意將元類的概念略去,因?yàn)轭惙椒▽?shí)際是存儲在元類中的颁褂,但是在此為了方便理解,同時也為后期進(jìn)階做準(zhǔn)備彩届。
上圖中涉及到了堆樟蠕、棧、代碼區(qū)等內(nèi)容吓懈,具體可以參考iOS中的內(nèi)存管理和 C語言中內(nèi)存分配和linux內(nèi)存管理和深入淺出-iOS內(nèi)存分配與分區(qū)
3.OC中的類方法和實(shí)例方法以及函數(shù)
OC和C中的函數(shù)的對比耻警,其實(shí)很簡單甘穿,在這里直接上代碼温兼,我覺得對于身為程序員的自己來說武契,可能會更加清晰咒唆,注意點(diǎn):在Java中對象可以直接調(diào)用類方法,但是在OC中對象不能調(diào)用類方法敦腔,必須通過類調(diào)用類方法符衔。靜態(tài)方法、類方法和對象方法的區(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語言中的函數(shù)一樣躺盛,都是用來保存一段特定功能的代碼
*OC中定義一個方法槽惫,也分為聲明和實(shí)現(xiàn)辩撑,聲明在@interface中合冀,實(shí)現(xiàn)寫在@implementation
*
*C語言中的函數(shù)分為兩種:內(nèi)部函數(shù)和外部函數(shù)
*OC中的函數(shù)也分為兩種:類方法和對象方法
*類方法只能用類名調(diào)用,對象方法只能用對象調(diào)用
*OC中的類方法用+表示峭判,OC中的對象方法用-表示
*
*編寫C語言函數(shù)的規(guī)律:1.確定函數(shù)名稱林螃;2.確定形參疗认;3.確定返回值伏钠;4.確定返回值類型
*編寫OC方法也有規(guī)律贝润,規(guī)律和C語言一模一樣
*/
/*C語言方法
void about();
void about()
{
printf("model=cpu=size=color");
}
*/
//注意:OC中的方法,如果沒有形參不需要寫()华畏,而是直接寫一個亡笑;
//為什么OC中沒有形參不需要寫()呢仑乌?因?yàn)镺C方法中的()有特殊用途,OC方法中的()是用來括住數(shù)據(jù)類型的
//行為的聲明
-(void)about;
/*
*C語言中的函數(shù):1.沒有返回值沒有參數(shù)的函數(shù)衙传;2.有返回值沒有參數(shù)的蓖捶;3.有返回值有參數(shù)的俊鱼;4.沒有返回值有參數(shù)的
*OC中的方法也有四種
*/
//有返回值沒有參數(shù)的畅买。例如:讀取短信
-(char *)loadMessage;
//有返回值有參數(shù)的谷羞,例如:打電話
//int signal(int number); C語言中的函數(shù)
//注意:OC中的方法如果有參數(shù),那么每個參數(shù)的數(shù)據(jù)類型前面必須加一個:
//注意:當(dāng)前的有參數(shù)的方法的方法名稱是 signal: 冒號也是方法名稱的一部分
-(int)signal:(int)number;
//有返回值,并且有多個參數(shù)的雁歌,發(fā)短信
//int sendMessage(int number,char* content);
//為了提高閱讀性知残,OC方法允許我們給每一個參數(shù)添加一個標(biāo)簽來說明當(dāng)前參數(shù)的含義
-(int)sendMessageWithNumber:(int)number andContent:(char*) content;
//-(int)sendMessage:(int)number :(char*) content; //當(dāng)前的方法名稱叫做:sendMessage::
//沒有返回值求妹,有參數(shù)的函數(shù)
-(void)callWithNumber:(int) number;
//計算器功能(類方法)
//如果你不想每次使用方法都需要創(chuàng)建對象并且開辟存儲空間
//并且如果該方法中沒有使用到屬性(成員變量),那么你可以把這個方法定義為類方法
//對象方法用對象調(diào)用 類方法用類名調(diào)用
//-(int)sumWithNumber1:(int)number1 andNumber2:(int) number2;
//只需要將對象方法的-號轉(zhuǎn)換成+制恍,那么就定義了一個類方法
//注意:如果實(shí)現(xiàn)了一個類方法,就必須去實(shí)現(xiàn)類方法
//如果實(shí)現(xiàn)的是一個對象方法何吝,那么就必須去實(shí)現(xiàn)對象方法
/*
*類方法和對象方法的區(qū)別
*0.對象方法以-開頭爱榕;類方法以+開頭
*1.對象方法必須用對象調(diào)用黔酥,類方法必須用類調(diào)用
*2.對象方法中可以直接訪問屬性(成員變量),類方法中不可以直接訪問屬性(成員變量)
*3.類方法的優(yōu)點(diǎn)棵帽,調(diào)用類方法的效率會比調(diào)用對象方法高
*4.類方法和對象方法可以進(jìn)行相互調(diào)用
*4.1對象方法中可以直接調(diào)用類方法
*4.2可以在類方法中間接調(diào)用對象方法
*4.3在類方法中可以直接調(diào)用其他方法
*4.4對象方法中可以直接調(diào)用對象方法
*/
/*
*類方法的應(yīng)用場景
*如果方法中沒有使用到屬性(成員變量)岖寞,那么能用類方法就用類方法
*類方法的執(zhí)行效率比對象方法高
*
*類方法一般用于定義工具方法
*字符串查找
*文件操作
*數(shù)據(jù)庫操作
*/
+(int)sumWithNumber1:(int)number1 andNumber2:(int) number2;
@end
//2.編寫類的實(shí)現(xiàn)
@implementation IPhone
//行為的實(shí)現(xiàn)
-(void)about
{
// NSLog(@"打印本機(jī)信息");
//如果在對象方法中想訪問該對象的屬性仗谆,可以直接寫上_屬性名稱即可
[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];//在類方法中隶垮,可以簡介調(diào)用對象方法狸吞,但是在企業(yè)開發(fā)中指煎,不建議這樣子使用
return number1+number2;
}
@end
int main(int argc, const char * argv[]) {
//1.通過類創(chuàng)建對象
IPhone *p=[IPhone new];
p->_color=KIColorBlace;
p->_model=4;
p->_cpu=1;
p->_size=3.5;
//3.獲取對象的屬性
// NSLog(@"size=%f,color=%i,model=%i,cpu=%i",p->_size,p->_color,p->_model,p->_cpu);
//4.如果給對象發(fā)消息(如果調(diào)用對象的方法)
[p about];
//注意:OC中的NSLog對C語言中的字符串支持不是很好至壤,如果返回的是中文的C語言字符串可能輸出是亂碼像街,也可能什么都不輸出
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)建一個對象
IPhone *p1=[IPhone new];
//2.利用對象調(diào)用假發(fā)運(yùn)算方法
// [p1 sumWithNumber1:1 andNumber2:2];
}
4.OC成員變量镰绎、局部變量、全局變量的區(qū)別以及內(nèi)存分析
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
//寫在類聲明的大括號中的變量随静,我們稱之為成員變量(或者屬性挪挤,實(shí)例變量)
//注意:
//1.成員變量不能離開類关翎,離開類以后就不是成員變量纵寝;
//2.成員變量不能在定義的同時進(jìn)行初始化星立;
//3.成員變量只能通過對象來訪問
//存儲在:堆(當(dāng)前對應(yīng)的堆的內(nèi)存空間中)
//存儲在堆中的數(shù)據(jù)绰垂,不會被自動釋放劲装,只能程序員手動釋放
int age;
}
@end
@implementation Person
@end
//寫在函數(shù)和大括號外部的變量占业,我們稱之為全局變量
//作用域:從定義的那一行開始纯赎,一直到文件末尾
//全局變量可以先定義再初始化犬金,也可以定義的同時初始化
//存儲在:靜態(tài)區(qū)
//程序一啟動就會分配內(nèi)存空間,知道程序結(jié)束才會釋放
int a;
int b=10;
int main(int argc, const char * argv[]) {
//寫在函數(shù)或者代碼塊中的變量峰伙,我們稱之為局部變量
//作用域:從定義的哪一行開始瞳氓,一直到遇到大括號或者return
//局部變量可以先定義再初始化权均,也可以定義的同時初始化
//存儲在棧中
//存儲在棧中的數(shù)據(jù)有一個特點(diǎn)叽赊,系統(tǒng)會自動給我們釋放
int num=10;
return 0;
}
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
//寫在類聲明的大括號中的變量必指,我們稱之為成員變量(或者屬性塔橡,實(shí)例變量)
//注意:
//1.成員變量不能離開類霜第,離開類以后就不是成員變量;
//2.成員變量不能在定義的同時進(jìn)行初始化癞谒;
//3.成員變量只能通過對象來訪問
//存儲在:堆(當(dāng)前對應(yīng)的堆的內(nèi)存空間中)
//存儲在堆中的數(shù)據(jù)弹砚,不會被自動釋放桌吃,只能程序員手動釋放
int age;
}
@end
@implementation Person
@end
//寫在函數(shù)和大括號外部的變量,我們稱之為全局變量
//作用域:從定義的那一行開始逗物,一直到文件末尾
//全局變量可以先定義再初始化敬察,也可以定義的同時初始化
//存儲在:靜態(tài)區(qū)
//程序一啟動就會分配內(nèi)存空間尔当,知道程序結(jié)束才會釋放
int a;
int b=10;
int main(int argc, const char * argv[]) {
//寫在函數(shù)或者代碼塊中的變量椭迎,我們稱之為局部變量
//作用域:從定義的哪一行開始,一直到遇到大括號或者return
//局部變量可以先定義再初始化缴阎,也可以定義的同時初始化
//存儲在棧中
//存儲在棧中的數(shù)據(jù)有一個特點(diǎn)蛮拔,系統(tǒng)會自動給我們釋放
int num=10;
return 0;
}
在以上的代碼中已經(jīng)對成員變量
建炫、全局變量
疼蛾、局部變量
做了詳細(xì)的區(qū)分,但是在內(nèi)存中具體是如何存儲的察郁?還沒有一個明確的概念。通過閱讀一些博客稳捆,對物理存儲有了一定的了解眷柔,分析如下:
-
RAM和ROM區(qū)分
我們所說的內(nèi)存,其實(shí)指的就是RAM驯嘱,在程序運(yùn)行期間系統(tǒng)將ROM中的源代碼加載到RAM中鞠评,我們所說的棧、堆聋涨、全局區(qū)/靜態(tài)區(qū)牍白、常量區(qū)抖棘、代碼區(qū)其實(shí)都是位于RAM中切省。RAM:運(yùn)行內(nèi)存,不能掉電存儲般渡。
ROM:存儲性內(nèi)存驯用,可以掉電存儲儒老,例如內(nèi)存卡、Flash淘这。
由于RAM類型不具備掉電存儲能力(即一掉電數(shù)據(jù)消失)巩剖,所以app程序一般存放于ROM中佳魔。RAM的訪問速度要遠(yuǎn)高于ROM鞠鲜,價格也要高。App程序啟動榆苞,系統(tǒng)會把開啟的那個App程序從Flash或ROM里面拷貝到內(nèi)存(RAM)霞捡,然后從內(nèi)存里面執(zhí)行代碼碧信。另一個原因是CPU不能直接從內(nèi)存卡里面讀取指令(需要Flash驅(qū)動等等)。 RAM中五大分區(qū)詳解
- 棧區(qū)(stack):
存放的局部變量躏筏、先進(jìn)后出趁尼、一旦出了作用域就會被銷毀碴卧;函數(shù)跳轉(zhuǎn)地址住册,現(xiàn)場保護(hù)等;
程序猿不需要管理?xiàng)^(qū)變量的內(nèi)存凡人。主要負(fù)責(zé)函數(shù)模塊內(nèi)申請挠轴,函數(shù)結(jié)束時自動釋放岸晦,存放局部變量睛藻,函數(shù)變量
~棧區(qū)地址從高到低分配;- 堆區(qū)(heap):
通過malloc函數(shù)或new函數(shù)等操作符操作的得到冈在,需要程序員自己管理
ARC的內(nèi)存的管理包券,是編譯器再便宜的時候自動添加 retain、release付秕、autorelease侍郭;
~堆區(qū)的地址是從低到高分配- 全局區(qū)/靜態(tài)區(qū)(static):
包括兩個部分:未初始化過(.bss段區(qū)域) 励幼、初始化過(data段區(qū)域),即全局區(qū)/靜態(tài)區(qū)在內(nèi)存中是放在一起的有滑,初始化的全局變量和靜態(tài)變量在一塊區(qū)域毛好, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域肌访。- 常量區(qū):存放常量字符串艇劫;
- 代碼區(qū): 存放編寫的源代碼店煞,由系統(tǒng)自動加載進(jìn)入;
- 注意:也有人將全局區(qū)/靜態(tài)區(qū)(static)和常量區(qū)聯(lián)合在一起成為數(shù)據(jù)區(qū)酒请。
具體圖示如下圖所示:
5.函數(shù)與方法的區(qū)別
首先需要理解的一點(diǎn)是:方法是對象的行為羞反,函數(shù)是整個文件的一個功能塊昼窗。方法只能存在于類內(nèi)部阁将,函數(shù)可以存在于整個文件的任何地方做盅。具體代碼如下:
#import <Foundation/Foundation.h>
/*
*函數(shù)和方法的區(qū)別
*1.函數(shù)屬于整個文件,方法屬于某一個類亭敢,方法如果離開類就不行
*2.函數(shù)可以直接調(diào)用图筹,方法必須用對象或者類來調(diào)用
*注意:雖然函數(shù)屬于整個文件,但是如果把函數(shù)寫在類的聲明中就會不識別
*3.不能把函數(shù)當(dāng)做方法調(diào)用远剩,也不能將方法當(dāng)做函數(shù)調(diào)用
*
*
*方法的注意點(diǎn):
*方法可以只有聲明沒有實(shí)現(xiàn)瓜晤,也可以只有實(shí)現(xiàn)沒有聲明痢掠,編譯不會報錯,但是運(yùn)行會報錯
*如果方法只有聲明而沒有實(shí)現(xiàn)雄驹,則會報錯:1.reason:'+[Person demo]:unrecognized selector sent to class 0x100001140',發(fā)送了一個不能識別的消息淹辞,在Person類中沒有+開頭的方法
*reason:'-[Person test]:unrecognized selector sent to instance 0x100001140'
*類也可以只有實(shí)現(xiàn)沒有聲明,例如:@implementation Person : NSObjec ... @end
*/
@interface Person : NSObject
//對象方法的聲明
-(void)test;
//類方法聲明
+(void)demo;
@end
@implementation Person
//對象方法的實(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)體作為對象屬性的細(xì)節(jié)
當(dāng)結(jié)構(gòu)體作為函數(shù)(C語言中的稱呼)參數(shù)或者作為對象屬性的情況下彬向,結(jié)構(gòu)體是以拷貝結(jié)構(gòu)體屬性的方式進(jìn)行傳遞的娃胆,此過程傳遞的不是指針里烦。
結(jié)構(gòu)體作為屬性的代碼示例:
類模型
#import <Foundation/Foundation.h>
/*
*合理的設(shè)計一個“學(xué)生”類
*學(xué)生有*姓名*生日另個屬性和說出自己姓名生日的方法
*要求利用設(shè)計的學(xué)生類創(chuàng)建學(xué)生對象禁谦,并且說出自己的姓名和年齡
*/
//定義一個新類型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é)生對象
Student *student=[Student new];
[student say];
//2.設(shè)置學(xué)生對象的屬性
student->_name=@"lxh";
/*
*student->_birthday={1992,12,23};錯誤原因
*1.結(jié)構(gòu)體只能在定義的時候初始化
*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í)是將結(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);
*/
/*
*這種方式賦值也可以陈症,單個賦值
*/
student->_birthday.year=1992;
student->_birthday.month=12;
student->_birthday.day=23;
/*
*第三種賦值方式
*/
Date d={1992,12,23};
student->_birthday=d;
return 0;
}
歡迎關(guān)注我的個人微信公眾號,免費(fèi)送計算機(jī)各種最新視頻資源徙缴!你想象不到的精彩于样!