• 对象的存储细节


     

            

      

    
    

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

         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
    ");
                
            }  
            
        }
        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 中通常把类拆分开来,拆分成声明和实现两个部分。
  • 相关阅读:
    洛谷 P4707 重返现世
    多项式总结&多项式板子
    线性常系数齐次递推
    洛谷 P2791 幼儿园篮球题
    CF Gym 102028G Shortest Paths on Random Forests
    洛谷 P4705 玩游戏
    [NOI2018]冒泡排序
    PKUSC2019 改题记录
    PKUSC2019 没约记
    Codeforces Round #557 题解【更完了】
  • 原文地址:https://www.cnblogs.com/kongweiiwei/p/4650869.html
Copyright © 2020-2023  润新知