2. objC 动态绑定(dynamic binding)
来源:互联网 发布:sep软件 编辑:程序博客网 时间:2024/06/11 08:58
1 动态绑定理解
动态绑定,在编译期间,不能决定当前调用函数的地址;在程序运行时,通过当前对象的类型来判断当前调用函数的地址所在。这一点和C和C++不同,在C中,所有函数的调用都是在编译过程中所决定的。在C++中,只有virtual函数的调用是通过v-table在运行时进行查找的,其他都是静态调用。
动态调用速度慢,静态调用速度快。
2 动态绑定原理
2.1 SEL
SEL 是objc_selector结构的指针,objc_selector的结构如下
objc_selector 的GNU Objective-C的实现
typedefconststructobjc_selector{ void *sel_id; constchar *sel_types;} *SEL
objc_selector 的NeXT Objective-C的实现
没有查到相关的文档,在相关文章中,其实现直接就是一个字符串。从此函数也可以知道
NSLog(@"%s",@selector(say: usingLag:);将打印出say:usingLag:。说明@selector只是简单的翻译,不判断say:usingLag:函数是否被某个类定义过。
2.2 IMP
IMP是一个obj-c中,内部定义的函数指针:
/*** Definition of method type. When retrieving the implementation of a** method, this is type of the pointer returned*/typedefid (*IMP)(id, SEL
向Child的对象pChild发送say:(int) LagType的消息,[pChild say:0]。编译器会将上边的代码翻译为id objc_msgSend(pChild, @selector(say:), LagType);其中,此函数申明为id objc_msgSend(id theReceiver, SEL theSelector, ...),此函数将在theReceiver中isa所指向的类对象的objc_method_list方法列表中去查找SEL所对应的IMP函数地址,进而进行执行。
/** Method Template */ typedef struct objc_method *Method; struct objc_method { SELmethod_name; char *method_types; IMPmethod_imp; }; struct objc_method_list { struct objc_method_list *obsolete; int method_count;#ifdef __alpha__ int space;#endif struct objc_methodmethod_list[1]; /* variable length structure */ };
2.3 性能
显然,这种函数的调用的方法,显然要比静态绑定要慢的多。于是,在程序中,我们常常可以把函数的地址先记录下来,然后直接进行调用。如下边的代码,但是,通过我们实际测速,这两种方式,基本上相差很少,是由于在Class中还有一个方法地址的Cache,会大大加快函数调用方法。所以,在实际的调用过程中,objC的函数调用没有象想象中的那么慢。
例如:
patient.h文件@interface Person : NSObject{@privateNSMutableString* name;@privateNSMutableString* uid;@privateNSDate* birthday;@privateNSString* sex;}@property(nonatomic, retain) NSMutableString* name;@property(nonatomic, retain) NSMutableString* uid;@property(nonatomic, retain) NSDate* birthday;@property(nonatomic, retain) NSString* sex;/** */-(id) init:(NSMutableString*) persionId andBirthDay:(NSDate*) birth;-(void) printOut;@end/**the below is about the Patient */@interface Patient: Person{@privateNSMutableString* medical_insure_card_id;}@property(nonatomic, retain) NSMutableString* medical_insure_card_id;-(id) init:(NSMutableString*) personId andBirthDay:(NSDate *)birth andMedicalInsureCardId:(NSMutableString*) cardId;-(void) printOut;@end/***/@interface PaitentCreator:NSObject+(Patient*) CreatePatient;@endpatient.m文件@implementation Person@synthesize name;@synthesize uid;@synthesize birthday;@synthesize sex;-(id) init:(NSMutableString*) persionId andBirthDay:(NSDate*) birth{ id temp = [superinit]; if (!temp || self != temp) { returnnil; } self.uid = persionId; self.birthday = birth; returnself;}-(void) printOut{ //NSLog(@"the person name is %@ uid = %@ birthday = %@",self.name,self.uid,[self.birthday description] ); NSLog(@"the person name is %@ ",self.name);}-(void)dealloc{ if (uid != nil) { [uidrelease]; uid = nil; NSLog(@"uid release"); } if (birthday != nil) { [birthdayrelease]; birthday = nil; NSLog(@"birthday release"); } if (sex != nil) { [sexrelease]; sex = nil; NSLog(@"sex release"); } if(name != nil) { [namerelease]; name = nil; NSLog(@"name release"); } [superdealloc];}@end@implementation Patient@synthesize medical_insure_card_id;-(id) init:(NSMutableString*) personId andBirthDay:(NSDate *)birth andMedicalInsureCardId:(NSMutableString*) cardId{ id temp = [superinit:personId andBirthDay:birth]; if (!temp || self != temp) { returnnil; } self.medical_insure_card_id = cardId; returnself;}-(void) printOut{ [superprintOut]; //NSLog(@"the patient medical card id = %@",self.medical_insure_card_id);}-(void) dealloc{ if(medical_insure_card_id != nil) { [medical_insure_card_idrelease]; medical_insure_card_id = nil; } [superdealloc];}@end@implementation PaitentCreator+(Patient*) CreatePatient{ Patient* pTempPatient = [[Patientalloc] init]; [pTempPatient autorelease]; return pTempPatient;}@end main.mtypedef void (*PrintInformation)(id, SEL); Patient* patient = [[Patientalloc] init:[[NSMutableStringalloc] initWithString:@"12345678"] andBirthDay: [NSDatedate] andMedicalInsureCardId:[[NSMutableStringalloc] initWithString:@"bj_jst_2012.1.21_beijing_china"]]; patient.name = [[NSMutableStringalloc] initWithString:@"Zhao^QiaoZhuan^^^"]; PrintInformation printFun = nil; printFun = (PrintInformation)[patient methodForSelector:@selector(printOut)]; for (int i = 0; i < 10000; ++i) { printFun(patient,@selector(printOut)); }//12286 - 7643 = 4643ms NSLog(@"------------------------------------------------------------------"); NSLog(@"------------------------------------------------------------------"); NSLog(@"------------------------------------------------------------------"); for (int i = 0; i < 10000; ++i) { [patient printOut]; }//16988 - 12287 = 4701ms
回想,在第一节中dynamic typing的讲解,知道performSelector等函数是和动态绑定中,查找函数有关系的。
- 2. objC 动态绑定(dynamic binding)
- java 动态绑定 dynamic binding
- C++ 动态绑定Dynamic binding
- 静态绑定(static-binding) 动态绑定(dynamic-binding)
- C#4.0 动态绑定(Dynamic Binding)
- 如何理解C++中的动态绑定(dynamic binding)
- 如何理解C++中的动态绑定(dynamic binding)
- 多态和动态绑定(polymorphism and dynamic binding)
- dynamic region binding task flow(region 动态绑定流taskflow)
- C++ - 继承(inheritance) 和 动态绑定(dynamic binding) 简介
- 虚函数与动态绑定 / Virtual function and Dynamic Binding
- Java中的多态(polymorphism)和动态绑定(dynamic binding)
- java中转型(upcasting)与动态绑定(dynamic binding)或者后期(late binding)细节
- java中转型(upcasting)与动态绑定(dynamic binding)或者后期(late binding)细节
- 虚函数(virtual)与多态(polymorphism)、动态绑定(dynamic binding)
- 【Java Learning】重载、多态和动态绑定——Overloading、Ploymorphism&Dynamic binding
- 1. objC 动态类型(dynamic typing)
- Dynamic Binding
- Fedora下搭建Android开发环境
- ORACLE完全恢复和不完全恢复的区别
- android修改wifi设备名
- ORACLE 恢复单个数据文件 非SYSTEM表空间或者撤销表空间
- GoogleTest项目
- 2. objC 动态绑定(dynamic binding)
- ORACLE单个控制文件丢失的恢复
- c++计算程序运行时间
- 产生[low,up)中m个不同的随机数,m<=up-low
- 数据库连接池技术中dbcp、c3p0、jndi
- 不用+、-、×、÷做加法
- ORACLE主要的系统表和数据字典视图
- poj 2935 bfs
- ORACLE物理文件存储位置查询语句