6.4,重载方法的调用
让我们继续关注“06-NSobjecs.m”文件,请大家参考一下下面的代码:
1 Class cattle_class = cattle->isa;
2 MyClass my_cattle_class = cattle->isa;
3 SEL say = @selector(saySomething);
4 IMP cattle_sayFunc = [cattle methodForSelector:say];
5 cattle_sayFunc(cattle, say);
6
7 Class redBull_class = redBull- >isa;
8 MyClass my_redBull_class = redBull- >isa;
9
10 IMP redBull_sayFunc = [redBull methodForSelector:say];
11 redBull_sayFunc(redBull, say);
本节的内容和6.3节的内容比较类似,关于代码部分笔者认为就不需要解释了,如果同学们有所不熟悉的话,可以参考一下第5章的内容。
在我们的cattle类和Bull类里面,都有saySometing这个实例方法。我们知道只要方法的定义相同,那么它们的SEL是完全一样的。我们根据一个SEL say,在cattle和redBull对象里面找到了他们的函数指针。根据6.3节的讲述,我们知道当runtime接收到寻找方法的时候,会首先在这个类里面寻找,寻找到了之后寻找的过程也就结束了,同时把这个方法的IMP返回给我们。所以,在上面的代码里面的cattle_sayFunc和redBull_sayFunc应该是不一样的,如图6-4所示:
图6-4, cattle_sayFunc和redBull_sayFunc的地址
6.5,超类和子类中的Class
在类进行内存分配的时候,对于一个类而言,runtime需要找到这个类的超类,然后把超类的Class的指针的地址赋值给isa里面的super_class。所以,我们的cattle里面的Class应该和redBull里面的Class里面的super_class应该是完全相同的,请参照图6-5:
图6-5, cattle里面的Class和redBull里面的Class里面的super_class
6.6,实例变量的内存分配的位置
我们先来回忆一下对象是怎样被创建的。创建对象的时候,类的内容需要被调入到内存当中我们称之为内存分配(Allocetion),然后需要把实体变量进行初始化(Initialization),当这些步骤都结束了之后,我们的类就被实例化了,我们把实例化完成的类叫做对象(objecs)。
对于内存分配的过程,runtime需要知道分配多少内存还有各个实例变量的位置。我们回到“MyNSobjecs.h”,参照如下代码:
1 typedef struct objc_ivar* Ivar_t;
2 typedef struct objc_ivar_List {
3 int ivar_count;
4 struct objc_ivar {
5 const char* ivar_name;
6 const char* ivar_type;
7 int ivar_offset;
8 } ivar_List[1];
9 } IvarList, *IvarList_t;
我们仔细看看第5行的ivar_name,顾名思义这个是实例变量的名字,第6行的ivar_type是实例变量的类型,第7行的ivar_offset,这个就是位置的定义。runtime从类的isa里面取得了这些信息之后就知道了如何去分配内存。我们来看看图6-6:
图6-6,实例变量在内存中的位置
在cattle里面,我们看到了第一个实例变量是isa,第二个就是我们定义的legsCount。其中isa是超类的变量,legsCount是cattle类的变量。我们可以看出来,总是把超类的变量放在前头,然后是子类的变量。
那么对于redBull而言是什么样子呢?我们来看看图6-7
图6-7,redBull里面的实例变量的位置
我们通过图6-7可以发现redBull的Class里面的skincolor的位置偏移是8,很明显,runtime为isa和legsCount预留了2个位置。
总结以上是内存溢出为你收集整理的Objective-C 2.0 with Cocoa Foundation---NSObject的奥秘(4)全部内容,希望文章能够帮你解决Objective-C 2.0 with Cocoa Foundation---NSObject的奥秘(4)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)