一、类、对象在内存中的存储

/*
内存分区:
栈:局部变量
堆:程序员自己写代码申请开辟的 程序员自己维护,编译器现在帮我们自动优化了,它在合适的给我们加上了释放空间的语句,所以我们现在写的对象不会造成内存泄露 全局区:所有的全局变量和静态变量
常量区:所有的常量
代码区:程序编译后的指令集 类是模板,肯定需要存在内存里面,因为实例化对象的时候需要根据这个模板来创建,那么存在内存里面,存在哪呢?? 类模板存在:全局区!
存的是:类的描述,还有所有的方法实现 每个对象都会有一个系统给我们的isa指针,但是这个指针无法直接使用,指针指向的是它所属的类的地址。 对象和类的原则:对象一定属于类。
对象调用方法,步骤其实是 先从指针变量找到对象所在堆空间地址,然后再通过这个对象里存的isa指针找到类中存的方法,再执行
*/ #import <Foundation/Foundation.h> @interface Person : NSObject{ @public
NSString *_name;
int _age;
} -(void)sayHi; @end @implementation Person //当类被加载的时候会调用这个方法
+(void)load{
NSLog(@"Person类被加载了");
} -(void)sayHi{
NSLog(@"大家好,我叫%@,今年%d岁",_name,_age);
} @end int a = ; void test(){ } @interface Dog : NSObject @end @implementation Dog //当类被加载的时候会调用这个方法
+(void)load{ NSLog(@"Dog类被加载了");
} @end int main(int argc, const char * argv[]) {
@autoreleasepool { //验证类在全局区
/*
NSLog(@"全局a的地址:%p",&a);//0x100004700 NSLog(@"类地址:%p",[Person class]); //0x100004688 NSLog(@"%p","abc"); // 0x100003b6e NSLog(@"%p",test);//0x1000013d0
*/ Person *p1 = [Person new]; Person *p2 = [Person new]; Person *p3 = [Person new]; NSLog(@"类地址:%p",[Person class]);//0x1000046e0 //因为下面的都是同一个类型。所以打印的isa地址都一样
NSLog(@"p1->isa=%p", [p1 valueForKey:@"isa"] );//0x1000046e0 NSLog(@"p2->isa=%p", [p2 valueForKey:@"isa"] );//0x1000046e0 NSLog(@"p3->isa=%p", [p3 valueForKey:@"isa"] );//0x1000046e0
Dog *js = [Dog new];
//因为下面的和上面的那些对象不是同一个类型,所以isa地址肯定不一样
NSLog(@"js->isa=%p",[js valueForKey:@"isa"]);//0x1000047f0 }
return ;
}

二、pragma的使用

/*
方法和函数弹出式窗口,里面包含了所有的方法和函数的声明列表以及实现列表,通过点击它可以方便又快速的跳转到某一个方法或函数那。 #pragma mark 分组名
作用:是在方法和函数弹出式窗口中增加分组信息,方便你快速的找到某个方法或函数。 #pragma mark - 分组名:
作用:跟上面一样,但是会增加分隔横线,这样看起来更直观。 */
#import <Foundation/Foundation.h> @interface Person : NSObject #pragma mark - 运动相关
-(void)run;
-(void)swimming;
-(void)playBasktball;
@end #pragma mark - Person实现类 @implementation Person #pragma mark - 运动实现
-(void)run{} -(void)swimming{} -(void)playBasktball{}
@end

三、对象作为方法的参数和返回值

1、对象作为方法的参数

/*
有参数的方法:
定义语法: -(void)方法名:(参数类型)参数1 方法名2:(参数类型)参数2;
把对象作为方法的参数:
语法:--(void)方法名:(类名 *)参数1; 调用:
[对象 方法名:对象]
例: [d displayPerson:p1]; 注意:
C以前分值传递和引用传递,现在OC也是一样。
所以也就是说,你把int char float 结构体变量 等等传给方法都是值传递。
值传递:在方法内改变了形参的值,外面的实参不会改变。
传递对象:是引用传递。
引用传递:在方法内改变了形参的值,外面的实参也会发生改变。 */ #import <Foundation/Foundation.h> #pragma mark - Person类
@interface Person : NSObject{
@public
NSString *_name;
int _age;
} @end @implementation Person @end #pragma mark - Display类
@interface Display : NSObject -(void)displayPerson:(Person *)p; //相当于这个方法需要传入一个Person对象 -(void)changePerson:(Person *)p;//改变Person对象的属性 -(void)changeInt:(int)number; @end @implementation Display
-(void)displayPerson:(Person *)p{ NSLog(@"p->_name=%@ p->_age=%d",p->_name,p->_age);
} -(void)changePerson:(Person *)p{
p->_name = @"习大大";
p->_age = ;
} @end #pragma mark - Main函数
int main(int argc, const char * argv[]) {
@autoreleasepool { //实例化Display对象
Display *d = [Display new]; //把对象作为方法的参数进行输出
//实例化Person对象,名字叫p1
Person *p1 = [Person new]; p1->_name = @"周小帅";
p1->_age = ; //传进去的对象是什么,就会打印什么
[d displayPerson:p1];//周小帅 16
}
return ;
}

2、对象作为方法的返回值

/*
方法定义:
-(返回值类型)方法名:参数列表;
-(int)
-(char)
-(int *)
-(struct student)
-(Person *) //相当于要返回一个Person类的对象
语法:
-(类名 *)方法名:参数列表 -(Person *)creatPerson; //返回一个Person对象
*/
#import <Foundation/Foundation.h> #pragma mark - Person类
@interface Person : NSObject{ @public
NSString *_name;
int _age;
} -(void)sayHi; @end @implementation Person -(void)sayHi{ NSLog(@"大家好,我叫%@,今年%d",_name,_age);
} @end #pragma mark - PersonFactory类 @interface PersonFactory : NSObject /**
* 这个方法返回一个Person对象
*/
-(Person *)creatPerson; @end @implementation PersonFactory -(Person *)creatPerson{
//new关键字无论何时都会开辟新的堆空间(新的对象)
Person *p = [Person new];
p->_age = ;
p->_name = @"周帅";
return p; //你要Person对象,我的p刚好就是person对象,所以可以返回p
//所以每次返回的地址都不一样
} @end
int main(int argc, const char * argv[]) {
@autoreleasepool {
PersonFactory *pf = [PersonFactory new];
//creatPerson里面方法用了new,所以每次返回的都是新的对象
//zs是一个Person对象,地址比如说是:0x11
Person *zs = [pf creatPerson];
//然后打印的是0x11地址里面存的成员数据,因为没有改过,所以打印的还是原来方法内改的值
NSLog(@"zs->name=%@ zs->age=%d",zs->_name,zs->_age);//周帅 16
//ls也一个Person对象,地址比如说是:0x12
Person *ls = [pf creatPerson];
//然后打印的是0x12地址里面存的成员数据,因为没有改过,所以打印的还是原来方法内改的值
NSLog(@"ls->name=%@ ls->age=%d",ls->_name,ls->_age);//周帅 16
//改的是0x11里面的数据
zs->_name = @"苍苍苍";
zs->_age = ;
//因为ls指向的0x12没改,所以打印的还是原数据
NSLog(@"ls->name=%@ ls->age=%d",ls->_name,ls->_age);//周帅 16
//因为zs指向的0x11里面的改了,所以打印的是改后的数据
NSLog(@"zs->name=%@ zs->age=%d",zs->_name,zs->_age);//苍苍苍 15
}
return ;
}

四、结构体作为类的成员

typedef struct {
int year;
int month;
int day; }myDate; @interface Person : NSObject{
@public
NSString *_name;
int _age;
BOOL _gender;
//出生年月日
myDate _birthDay;
//人可以养一条宠物
Dog *_chongwu; //代表是Dog对象类型
} /**
* 说自己生日的
*/
-(void)sayMyBirthDay;
@end
@implementation Person -(void)sayMyBirthDay{
NSLog(@"我出生于%d年%d月%d日",_birthDay.year, _birthDay.month,_birthDay.day);
_chongwu->_color = @"黄色";
}
@end
/* 结构体也可以作为类的成员。 本身类的成员属性的定义语法就是 : 类型 成员变量名;
所以只要符合这个语法的都行!
所以换句话来说,所有只要是类型的东西,都可以作为成员属性 结构体作为对象的成员:
在对象内部:成员名.成员 例:_birthDay.year
在外部:对象名->成员名.成员 例: p->_birthDay.year */ #import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [Person new];
p->_age = ; // p->_birthDay.year = 1998;
// p->_birthDay.month = 2;
// p->_birthDay.day = 3; //一次性赋值,需要强转,右边的小括号里面必须加这个结构体的类型
p->_birthDay = (myDate){,,}; //实例化某个对象属性
p->_chongwu = [Dog new]; [p sayMyBirthDay];
NSLog(@"出生于哪年%d",p->_birthDay.year);
//外部访问某一个属性(这个属性又是一个对象)的时候的赋值
p->_chongwu->_color = @"红色";
NSLog(@"养了条宠物,毛色是%@",p->_chongwu->_color);
}
return ;
}

五、多文件开发

/*
c语言中有多文件开发,oc中肯定也有。
多文件开发的原因:
1.我们的类代码太多,写在一个文件里面不利于观察。
2.项目是多个人一起开发的,如果写在一个文件里面不利于同时开发。
注意: 写好模块后,一定只能导入.h文件,不能导入.m文件。 多文件开发添加文件方式:鼠标右键,选择New File ,然后在选择Cocoa Class ,第一栏填名称,第二栏是表示继承哪里,一般情况下不需要修改,会自动穿件oc的头文件和.m文件。
*/

六、结构体与类的区别、函数与方法的区别

/*
结构体与类的区别:
1.语法区别。
2.结构体里面不能包含行为(方法、函数),类可以。
3.结构体成员不能写访问修饰符,但是类可以。
4.结构体里面不能有类的对象作为成员,但是类可以有结构体作为成员。
5.结构体数据保存在栈,对象数据保存在堆。
6.结构体是面向过程的思维产物,类是面向对象的思维产物。 函数与方法的区别:
1.语法不同。
2.函数可以直接调用,方法必须通过对象。
3.函数的声明可以写在任意位置,不包括属性列表的大括号里面。方法的声明只能写在@interface和@end之间,不包括属性列表的大括号里面。
4.函数的实现可以写在除了函数内的其他所有位置(不要写在@interface和@end之间),不包括属性列表的大括号里面,方法的实现只能写在@implementation和@end之间。
5.函数是面向过程的思维,方法是面向对象的思维。
*/

七、NSString的略详细介绍

/*

 NSString 是OC中的字符串类型

    用法:
NSString *str = @"字符串"; 1.NSString也是一个对象,所以也可以通过new来创建 2.NSString按格式化组成一个字符串 [NSString stringWithFormat:@"格式化字符串",值列表]; 例: NSString *str = [NSString stringWithFormat:@"哈哈,今年%d岁",16]; 3.OC中比较两个字符串是否相等: C语言:strcmp(字符串1,字符串2) == 0 代表相等; OC:[ OC字符串1 isEqualToString:OC字符串2]; 这个方法有一个BOOL类型的返回值,如果相等返回YES,否则返回NO 例:[str1 isEqualToString:str2] 注意:也可以直接把这个方法调用写在if括号里面判断 4.OC字符串怎么计算实际个数??(重点)
C语言:strlen(字符串); 计算实际占用的字节数 OC语言:[OC字符串 length]; 返回这个OC字符串的实际个数 例:[str length]; */ #import <Foundation/Foundation.h> @interface Person : NSObject{ @public
int _age;
}
@end @implementation Person @end int main(int argc, const char * argv[]) {
@autoreleasepool { //不用这种写法,因为这种对象主要是用来表示一个字符串
// NSString *str = [NSString new];
// str = @"字符串"; //直接这么用就行
// NSString *str = @"字符串";
//
// NSLog(@"%@",str);
//格式化字符串// NSString *str = [NSString stringWithFormat:@"哈哈,今年%d岁",16];
//
// NSLog(@"%@",str); //判断两个字符串是否相等
/*
NSString *str1 = @"哈哈";
NSString *str2 = @"哈哈"; BOOL res = [str1 isEqualToString:str2]; if (res) { NSLog(@"相等"); }else{ NSLog(@"不相等");
}
*/ /*
BOOL res = [@"哈哈" isEqualToString:@"哈哈"]; if (res) {
NSLog(@"相等");
}else{
NSLog(@"不相等");
}
*/ //获得OC字符串的实际个数
NSString *str = @"abcd 哈^";
unsigned long length = [str length];
NSLog(@"%lu",length);//7个 空格、符号等等都算
unsigned long length2 = [@"呵呵呵" length];
NSLog(@"%lu",length2);//3个 }
return ;
}

oc语言学习之基础知识点介绍(二):类和对象的进一步介绍的更多相关文章

  1. oc语言学习之基础知识点介绍(五):OC进阶

    一.点语法介绍 /* 以前封装后,要给属性赋值,必须调用方法 这样做,有两个缺点: 1.代码量多,调用方法要写的东西多. 2.看起来并不像是给属性赋值,也不像取值. 我们用点语法就可以更好的解决! 点 ...

  2. oc语言学习之基础知识点介绍(四):方法的重写、多态以及self、super的介绍

    一.方法重写 /* 重写:当子类继承了父类的方法时,如果觉得父类的方法不适合,那么可以对这个方法进行重新实现,那么这个就重写. 注意:也就是说,一定只能发生在父类和子类关系中. 然后是子类重新实现父类 ...

  3. oc语言学习之基础知识点介绍(一):OC介绍

      一.第一个OC程序 #import <Foundation/Foundation.h> //导入头文件 int main(int argc, const char * argv[]) ...

  4. oc语言学习之基础知识点介绍(三):类方法、封装以及继承的介绍

    一.类方法的使用 /* 像我们之前学的方法,必须先实例化这个类的对象才能调用这个方法,类方法不用实例化对象,直接调用这个方法. 之前学的方法调用的语法: [对象名 方法名]; //对象方法 类方法: ...

  5. c语言学习之基础知识点介绍(二):格式化控制符和变量的补充

    上节简单介绍了c语言中的一些基础知识点,本节将对之前介绍的不够详细的知识点进行补充. 格式化控制符的消息介绍: %d的其他控制符: 1.%md:m代表这个整数位占用多少位,m是一个整数.实际数字不足的 ...

  6. c语言学习之基础知识点介绍(三):scanf函数

    本节继续介绍c语言的基础知识点. scanf函数:用来接收用户输入的数据. 语法:scanf("格式化控制符",地址列表); 取地址要用到取地址符:&(shift+7) 例 ...

  7. c语言学习之基础知识点介绍(十):数组

    本节主要介绍数组. 一.数组 /* 数组:一个变量可以存n个变量. 语法:类型 数组名[长度(正整数)]; 例如:int score[5];//定义了一个int类型的数组,长度为5,可以保存5个数据. ...

  8. c语言学习之基础知识点介绍(六):if和switch结构

    本节主要说c语言中的分支结构. c语言中分支结构有两大类:一种是if,一种是switch. 一.if结构 //if结构,语法: //第一种: if(表达式){ //语句块 } //第二种: if(表达 ...

  9. c语言学习之基础知识点介绍(二十):预处理指令

    一.预处理指令的介绍 预处理命令:在编译之前触发的一系列操作(命令)就叫预处理命令. 特点:以#开头,不要加分号. #include: 文件包含指令 把指定文件的内容复制到相应的位置 #define: ...

随机推荐

  1. A Tour of Go Concurrency

    The next section covers Go's concurrency primitives. A Tour of Go Goroutines A goroutine is a lightw ...

  2. Oracle- 表的自增长创建

    Oracle创建自增长要先写序列还要去写触发器,不像MSSQLSERVER那样方便.但也是麻烦,记录如下: Oracle中,可以为每张表的主键创建一个单独的序列,然后从这个序列中获取自动增加的标识符, ...

  3. ECSHOP在线手册之 数据库结构说明 (适用版本v2.7.3)

    1.account_log 用户账目日志表 字段 类型 Null/默认 注释 log_id mediumint(8) 否 / 自增 ID 号 user_id mediumint(8) 否 / 用户登录 ...

  4. 如何关闭log4j中配置的spring或者hibernate的日志信息

    通常在建立一个web项目的时候,我们通常需要为其配置日志,以便了解启动过程中发生了什么,如果启动过程中发生了错误,则可以很方便的查看错误的信息,但是在项目部署到服务器上时,打印日志信息,需要耗费大量的 ...

  5. 秀一套每秒处理1500+个事务的profile

    秀一套每秒处理1500+个事务的profile,真实生产环境

  6. [C#源码]VS各版本转换器(支持VS2012,VS2013)

    项目名称:[C#源码]VS各版本转换器(支持VS2012,VS2013) 下载内容: (C#源码)VS各版本转换器 实现功能: 支持vs2003-vs2013的各版本转换,由高到低,由低到高都支持. ...

  7. Codeforces Round #323 (Div. 2) C. GCD Table 暴力

    C. GCD Table Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/583/problem/C ...

  8. dojo(四):ajax请求

    储备知识 1.在介绍新版本的ajax请求之前,需要先了解一些dojo/Deferreds. 初次听到“Deferred”这个概念,可能会觉得这是一个神秘的东西.实际上它在执行异步操作的时候非常强大,例 ...

  9. js操作json添加元素和数据的方法

    function addServerUrlToJson() { var json_tem = [{"name":"a","value":1} ...

  10. 升级ADT22.6后,Android模拟器无法创建

    这 两天,在社区里看到有小伙伴们反应,自己在Eclipse下无法创建Android模拟器的问题.起初,自己也没太在意,我一直使用的是 Genymotion模拟器.然后,问题不解决,总有那么一天会让自己 ...