代码改变世界

对象的存储细节

2015-07-16 12:02  另十  阅读(292)  评论(0编辑  收藏  举报
 

 

 

        

  


    分析这句代码在内存中的存储细节:

     Person *p = [Person new];


第一步:先把Person类的代码(属性和方法)加载到代码区(只会加载一次,内存里面只有一份代码)

第二步:代码执行到[Person new],

           [Person new] 做了3件事情

         1) 申请内存空间

            new 的时候申请的空间在内存的堆区(程序动态分配的内存空间)

         2)给实例变量初始化

            

            如果实例变量是基本数据类型,此时给初始化为0

            如果  。。。。OC字符串类型             null 

 

         3) 返回空间的首地址

       

            同时在堆内存中分配一个isa指针,每一个对象都包含一个isa指针.这个指针指向当前对象所属的类。 


第三步: p(指针变量) 存放在栈区,指向堆内存的首地址(注意这个地址不是isa存的对象所属的类)

 

 

 

修改实例变量就是找到指针p,然后修改它指向的属性


[p run];

         首先找p对应的堆区的空间,然后找到 _isa指针,再找到_isa指向的

         代码区的空间,然后到该空间中找 方法

 

        [Person new] 做了3件事情

         1) 申请内存空间

         2)给实例变量初始化

         3) 返回空间的首地址

        

        1、申请的空间在内存的哪个区?

           new 的时候申请的空间在内存的堆区(程序动态分配的内存空间)

           当new的时候内存的布局是这么样的

     

           初始化的时候:

           如果实例变量是基本数据类型,此时给初始化为0

           如果  。。。。OC字符串类型             null

        

        

        2、实例变量又保存在什么地方

          堆区

         

          p(指针变量) 存放在栈区

        

        3、对象方法保存在什么地方

          代码区

        

        4、为什么使用 [p run]; 就可以调用方法了 ?如何调用的

        

         首先找p对应的堆区的空间,然后找到 _isa指针,再找到_isa指向的

         代码区的空间,然后到该空间中找 方法

        

        

        5、一个类可以创建多个对象

 

 

代码:

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    @public
    int _age;
    float _weight;
    NSString *_name;
}
//行为
-(void)run;
@end

@implementation Person
-(void)run{

    NSLog(@"人正在跑");

}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //创建对象
        Person *p = [Person new];
        p->_name = @"柯南";
        p->_age = 13;
        
        //_age 0
        //_name null
        
        NSLog(@"姓名:%@,年龄:%d,体重:%f",p->_name,p->_age,p->_weight);
        
        [p run];
        
        
        //又创建了一个对象p1
        Person *p1 = [Person new];
        p1->_name = @"贝娜";
        p1->_age = 33;
        
        NSLog(@"姓名:%@,年龄:%d,体重:%f",p1->_name,p1->_age,p1->_weight);
        
        [p1 run];
        
        
    }
    return 0;
}

 

2015-07-16 11:56:04.569 03-对象的存储细节[699:38284] 姓名:柯南,年龄:13,体重:0.000000
2015-07-16 11:56:04.570 03-对象的存储细节[699:38284] 人正在跑
2015-07-16 11:56:04.570 03-对象的存储细节[699:38284] 姓名:贝娜,年龄:33,体重:0.000000           //体重是没有赋值的,所以就根据类型默认值
2015-07-16 11:56:04.570 03-对象的存储细节[699:38284] 人正在跑

 

5-函数和对象方法的区别 

函数和对象方法的区别
 
对象方法:

-(void)run;
(
1)对象方法的实现只能写在@implementation...@end中,对象方法的声明只能写在 @interface...@end中间
(
2)对象方法都以-号开头,类方法都以+号开头

(3)对象方法只能由对象来调用,类方法只能由类来调用,不能当做函数一样调用

(4)函数属于整个文件,可以写在文件中的任何位置,包括@implementation...@end中,但写在 @interface...@end会无法识别,函数的声明可以再main函数内部也可以在main函数外部。

(5)对象方法归类\对象所有

函数:
void run(){
} (
1)所有的函数都是平行的

(2)函数不存在隶属关系

(3)使用的时候可以直接调用

(4)不可以访问对象中的成员变量

 

 

 【掌握】06-常见错误

常见错误:

  (1)@interface @end和@implementation @end不能嵌套包含 

 

  (2)只有类的声明没有类的实现  


      只有@interface没有@implementation时,程序编译能够通过,但是执行报错 ,所以除了你要把这个方法定义成私有方法时(没声明,有实现)外,必须同时有@interface,@implementation


  (3)漏写@end 

  (4)两个类的对象声明顺序(可以把顺序打乱) ,但声明必须在在实现前

  (5)成员变量没有写在{}里

  (6)方法的声明写在了{}里面

  (7)在声明时,请注意成员变量不能脱离对象而独立存在

  (8)方法无法像函数那样的调用

  (9)成员变量和方法不能用static等关键字修饰,不要和c语言混淆

  (10)类的实现可以写在mian函数后面,在使用之前只要有声明就可以 

 

 (11)

     

  语法检查上没有问题,因为编译器发现你已经声明了,运行时时错误的

    '-[Person run]: unrecognized selector sent to instance 0x100103410'  不能向实例发送消息,即是找不到方法


这个错误会让程序停在那,不会退出


 

  这个错误可以扑捉

#import <Foundation/Foundation.h>


@interface Car : NSObject

{
    @public
    int _lunzi;
}

-(void)stop;

@end



int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
     Car *car = [Car new];

  
        @try {
            //有可能会出错的代码
            [car stop]; //语法检查上没有问题,运行时时错误的
        }
        @catch (NSException *exception) {
            //错误的处理方法
            NSLog(@"出错了,您调用的方法没有实现!");
            NSLog(@" %@ ",exception);  //打印出错误的信息
        }
        @finally {
            
            printf("xxxxxx\n");
            
        }  
        
    }
    return 0;
}


@implementation Car


@end

 

2015-07-16 14:14:15.714 06-常见错误汇总[852:56541] -[Car stop]: unrecognized selector sent to instance 0x100301990
2015-07-16 14:14:15.716 06-常见错误汇总[852:56541] 出错了,您调用的方法没有实现!
2015-07-16 14:14:15.716 06-常见错误汇总[852:56541]  -[Car stop]: unrecognized selector sent to instance 0x100301990 
xxxxxx

 

 

-对象和方法之间的关系

 


对象和方法之间的有二种关系

一)对象作为方法的参数 二)对象作为方法的返回值
对象和方法之间的关系
 
    1)对象作为方法的参数
  
    //      方法名       形参数类型    形参数名
     -(void)dispPerson:(Person *) person;
 
       
      Person *p1 = [Person new];
 
      [p dispPerson:p1]  //对象作为方法的实参
 
 
 
    2)对象作为方法的返回值
 
#import <Foundation/Foundation.h>
//               0     1        2
typedef enum{kSexMan,kSexWomen,kSexYao} Sex;

//定义个person类
@interface Person : NSObject
{
    @public
    NSString *_name;
    Sex _sex;
}

//对象作为方法的参数
-(void)dispPerson:(Person *) person;
//对象作为方法的返回值
-(Person *)changSex:(Person*) person;
@end

@implementation Person
//对象作为方法的参数
-(void)dispPerson:(Person *) person{

    NSLog(@"姓名:%@,性别:%d",person->_name,person->_sex);
}

//对象作为方法的返回值         p1
-(Person *)changSex:(Person*) person{

    //修改姓名
    person->_sex = kSexWomen;

    return person;  //p1
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //创建对象p
        Person *p = [Person new];
        
        //创建对象p1
        Person *p1 = [Person new];
        p1->_sex = kSexYao;
        p1->_name = @"刷我的卡";
        
        Person *p2 = [Person new];
        p2->_name = @"张三丰";
        p2->_sex = kSexWomen;
       
        [p dispPerson:p2];    


//修改性别 //[p changSex:p1]; Person *p3 = [p changSex:p1]; //p3 p1 都指向同一个空间 NSLog(@"姓名:%@,性别:%d",p3->_name,p3->_sex); } return 0; }
2015-07-16 15:10:04.581 07-对象和方法之间的关系[882:65770] 姓名:张三丰,性别:1
2015-07-16 15:10:04.581 07-对象和方法之间的关系[882:65770] 姓名:刷我的卡,性别:1

 

补充:
import有两个作用:
一是和include一样,完完全全的拷贝文件的内容;
二是可以自动防止 文件内容的重复拷贝(即使文件被多次包含,也只拷贝一份)。
在使用命令行进行编译链接文件的时候,通常是把.m文件单文件编译,然后再把所有的目标文件 链接,
但是在Xcode中,是把所有的.m文件都进行编译链接的,如果出现重复定义的错误,那大部 分问题根源应该就是文件内容被重复包含或者是包含.m文件所引起的。
源文件中不论是使用include还是import,都不能包含.m或者是.c文件,只能放声明。因此,在OC 中通常把类拆分开来,拆分成声明和实现两个部分。