- (Class)class {
return object_getClass(self); // 把消息接收者传进去,获取消息接收者的类(
self就是class方法当前的调用者,也就是消息接收者)
}
MJPerson 跟[MJPerson class] 是一个意思,都是代表类对象
元类对象跟类对象是不一样的
上面注释掉的4行代码跟下面的4行代码是一样的
=============================super面试题================
person这个指针变量里面存储的是isa这个指针变量的地址值,isa这个指针变量里面存储的又是
[MJPerson class]的地址值。
平时我们正常调用方法是怎么找到对应的isa的呢?
答:从表面上看是 person ->isa ,这样找到isa,但实际上本质是,取出person指针所指向的那一块内存
空间的前8个字节,也就是isa指针(isa转成汇编本质,实际上就是拿第一个成员person ->第一个成员,然后
找到类对象),然后通过isa就能找到对应的类对象,就可以开始查找方法,查找到后开始调用了。
[person 方法]为什么能够调用成功?
答:通过person这个指针找到对应的实例对象的内存(也就是person这个指针变量所指向的内存空间)
并取出最前面的8个字节,因为最前面8个字节就是isa指针。取出isa指针后(或者取出最前面8个字节以后)
就能找到类对象,去缓存里面找方法或者方法列表中找方法。
上图中obj能够调用成功,是因为obj指向的cls(也就是这块内存)前8个字节(存储的内容)刚好是
MJPerson类对象的内存地址值
函数调用问题:
函数里面局部变量分配在栈空间
左边这块区域是我们这个函数的栈空间,[MJPerson class] 和@“123”在全局区
self.name 就是获取_name,怎么找到_name,那不就是这么去找嘛self -> _name,而self就是当前方法的调用者,此时print方法的调用者是obj,所以此时的self就是obj
找_name的本质:self指向那个结构体,self存储的地址值就是整个结构体的地址值,相当于self存储的地址值就是isa变量的地址值。所以self -> _name,也就是找_name的时候,忽略前面8个字节,找下面8个字节,就能找到_name了。找内存的本质,就是找到内存地址,再取出内存地址里面的值
[super viewDidLoad]会先定义一个隐藏的局部结构体变量。如果注释掉[super viewDidLoad],就会出现坏内存访问,因为查找_name的时候,不知道找谁了
===================验证=========
此时person实例对象对应的结构体是{isa, country, age}也就是属性的定义顺序,决定了属性在结构体里面的位置顺序
=====================
验证1
验证1
验证1 验证2
验证2
验证2
从第二个成员的父类开始搜索方法
网友评论