一 函数调用概述objective-c
Objective-C不支持多重继承(同Java和Smalltalk),而C++语言支持多重继承。编程
Objective-C是动态绑定,它的类库比C++要easy操做。安全
Objective-C在执行时可以赞成依据字符串名字来訪问方法和类。还可以动态链接和加入类。 C++ 跟从面向对象编程里的Simula 67(一种早期OO语言)学派,而Objecive-C属于Smalltalk学派。Simula 67学派更安全。因为大部分错误可以在编译时查出。 在C++里,对象的静态类型决定你可否够发送消息给它,而对Objective-C来讲。由动态类型来决定。数据结构
Objective-C比C++ 更强调类型的动态性,尽管牺牲了一些运行性能。但由于模型清晰,而牺牲的这些性能可以在今天由更先进的编译技术来弥补。
ide
二 消息的产生函数
在Objective-c中消息一直到执行时才干绑定到相应的函数:
[reveiver message];
编译器在处理时会将上面的表达式处理称如下这样的形式:
objc_msgSend(receiver,selector);
假设方法有多个參数的时候会处理成如下这样的形式:
objc_msgSend(receiver,selector,arg1,arg2。…….);
现在咱们知道了在Objective-c中函数调用都会被编译器进行预处理,调用obj_msgSend函数进行消息的发送。这里需要弄明确的selector是什么东东?receiver是怎么样来调用指定的函数的,它在背后是如何实现的?如下将逐一解释。 post
三 类对象中与消息有关的结构
首先看一下与消息传递有关的几个数据结构和数据类型。
1. struct objc_method_list **methodLists
在上一节中知道在类对象objc_class中有一个结构体 struct objc_method_list **methodLists ,它事实上是方法的映射表。
struct objc_method_list { struct objc_method_list *obsolete int method_count struct objc_method method_list[1] }
在objc_method_list中包括一个objc_method结构体
struct objc_method { SEL method_name char *method_types IMP method_imp }
对于每个參数如下将详细说明。性能
(A selector is the name used to select a method to execute for an object, or the unique identifier that replaces the name when the source code is compiled. A selector by itself doesn’t do anything. It simply identifies a method. The only thing that makes the selector method name different from a plain string is that the compiler makes sure that selectors are unique. )仅仅要方法的名字(包含參数序列)一样,那么它们的 ID都是一样的。spa
就是 说,不管是超类仍是子类,不管是有没有超类和子类的关系,仅仅要名字一样那么ID就是同样的。指针
- (void) viewDidLoad { [super viewDidLoad]; //声明一个函数指针 void (*MyPrint)(id,SEL,NSString*); MyPrint = ( void (*)(id,SEL,NSString*) )[self methodForSelector:@selector(Print:)]; MyPrint(self,@selector(Print:),@"Hello World"); } - (void) Print:(NSString*) str { NSLog(@"%@",str); }
首先,编译器依据函数声明生成一个惟一函数ID,每个实例变量的第一个成员是isa,它指向类对象,在类对象中保存有该类所拥有的方法列表,经过生成的的函数ID可以找到其相应的函数地址,从而调用函数。假设在当前类对象的函数映射表中没有找到函数的话,就继续搜索其父类中(每个类对象的super_class 存储了父类的类对象地址),假设到达其根类仍是没找到的话,会报执行时错误。 其步骤例如如下图所看到的:
消息的成功传递依赖于两个重要的要素,经过实例中的 isa指针找到实例所属的类对象,而后经过类对象中的消息映射表找到所要调用的函数。
首先经过传递的selector參数找到消息映射表中的函数。而后调用函数,将实例的地址和參数传递给调用的这 个函数。最后返回返回值。
类类型的存在使objective-c拥有了执行时识别,动态建立,序列化等机制。
3.消息接收者对象(指向消息接收者对象的指针)以及方法中指定的參数传递给方法实现 IMP。
4.最后。将方法实现的返回值做为该函数的返回值返回。
注:编译器会本身主动插入调用消息函数objc_msgSend。咱们无须在代码中显示调用该消息函数。
五 消息传递小结
到这里,咱们已经大体明确了Objective-c 中消息的传递的整个过程。事实上假设你熟悉MFC的话,你会发现Objective-c的执行时和MFC的RTTI挺像的。
下图是MFC的执行时机制,CRuntimeClass至关于Objectiv-c的object_clas类对象,在CRuntimeClass中有指向基类函数的指针。与MFC不一样的是object_class没有相似与m_pNext_ClassMFC成员。
1.编译器会将消息转换为对消息函数 objc_msgSend的调用,该函数有两个基本的參数:消息接收者 receiver 和消息相应的方法ID,即SEL, 同一时候接收消息不定參数列表。
如下再作一下具体消息传递过程:
正因为有像CRuntimeClass和object_class这些类类型的存在才使得它们拥有了执行识别。动态建立。序列化等机制。
下一节将对消息传递作进一步的深层次探究。