先看下我们经常写的init方法,都会先调用父类的init方法
OC代码通过命令xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc xxx.m -o xxx.cpp转换为c++代码如下
c++代码可以看出[super init]其实是调用了objc_msgSendSuper方法,并且传了两个参数,第一个参数是一个objc_super结构体对象,而且有两个成员变量
一个是receiver,一个是super_class,也就是上面的self是给了receiver,而class_getSuperclass(objc_getClass("WPPerson"))是给了super_class,也就是第一个成员是当前实例对象self,第二个成员是self的父类,由于WPPerson是直接继承的NSObject,所以第二个成员就是NSObject,这是第一个参数结构体中的内容,第二个参数就是init方法了
接着看下objc_msgSendSuper方法的申明
注释里面选中的那一段的意思是方法查找从objc_super结构体中的第二个成员开始查找,也就是跳过self的类对象,直接从父类的类对象中查找init方法,所以这里的super的作用就是为了告诉编译器查找init方法需要从父类类对象中开始查找
上面是通过转为为c++代码的形式来查看super关键字的底层原理,下面我们从汇编层面看下super关键字的原理
接下来我们在self = [super init]代码行打上断点,然后将汇编模式打开Debug-》Debug Workflow-》勾上Always show Disassembly,运行代码,这时会进入汇编界面
可以看出[super init]其实是调用了objc_msgSendSuper2的方法,而且objc_msgSendSuper2和objc_msgSendSuper的实现还有点差别,之前的objc_msgSendSuper中的第一个参数中的结构体的第二个成员是父类,但是objc_msgSendSuper2中是当前类,只是在objc_msgSendSuper2方法内部转换成了父类,其他的就都是一样了,所以将OC转换为c++代码是作为参考的,有些地方不够准确,但是大部分地方都是和实际的实现一样。
网友评论