Class 类型、Selector 选择器、SEL 类型、函数指针

一、Class 类型

  • 机制:一个类在正确编译后,在这个被正确编译好的类里面,存在一个isa指针,用于存储类的方法及变量信息,这个isa指针是id类型。可以通过一个普通的字符串可能获取到这个Class类型对象,也可以通过此类的对象获取到此类的Class类型对象,获取到Class类型对象后,可以按类实例化后的对象一样使用它。在程序runtime可以通过类的Class类型对象获取到类实例化后的对象,也可以动态的获取在编译阶段无法确定的对象。
  • 因为,在类里面存储了类的所有信息,所以,可以通过类的名称或类的对象获取到Class类型对象。当然,也可以获取到超类的Class类型对象。
     1 // 通过类名称或对象,向此类或者对象发送class消息,获取此类的Class类型对象
     2 Class class = [类名称或对象 class];
     3 // 通过类名称或对象,向此类或者对象发送superclass消息,获取此类的超的Class类型对象
     4 Class superClass = [类名称或对象 superclass];
     5 // 通过类名称字符串,获取此类的Class类型对象
     6 Class class = NSClassFromString(类名称字符串);
     7 // 通过Class类型对象,获取此类的名称字符串
     8 NSString *classname = NSStringFromClass(Class 参数);
     9 // 向类对象发送消息,获取类的类名称,classname是一个固定参数,详细参考classname实现源码
    10 NSString *classname = [classobject classname];

二、Selector 选择器

  • 机制:选择器Selector是用于表示方法的,会根据方法的名称(参数序列),确定一个唯一的身份证明(其实,就是一个整数),(摸不准/*在不同的类里面相同名称相同声明的方法,其身份证明是相同的)。在runtime就不用对方法的名称进行比较,以确定要执行的是哪一个方法,只要通过一个整数就可以定位到相应的方法,然后就可以找到相应方法的入口地址,就可以执行方法了。在OC中消息的执行(方法的执行)与C语言直接找到函数地址入口方式相比,OC的消息机制从效率上讲是比较低下的。虽然,OC使用了Selector选择等方式进行寻找,总是要花费时间的。OC是兼容C语言的,也就是说可以使用C的函数指针方式,增加效率。当要求效率时,比如,当在一个大循环里,要使用某一功能时,就放弃对某一单一对象发送消息的方式(Selector),从而使用函数指针,这样就有和C一样的效率了。

三、SEL 类型

  • 在Selector选择器已经说了,在编译的时候,会根据方法的名字及参数序列,确定一个唯一的身份证明,这个身份证明就是一个SEL类型,可以通过方法名字取得方法的ID(SEL类型对象),也可以通过方法名称的字符串取得SEL类型对象。反之,也可以通过SEL类型对象(ID)取得方法名字。如下:

    1 // 通过方法名称,获取此方法的SEL类型对象
    2 SEL 变量名 = @selector(方法名称);
    3 // 通过方法名称字符串,获取此方法的SEL类型对象
    4 SEL 变量名 = NSSelectorFromString(方法名称字符串);
    5 // 通过方法的SEL类型对象及参数,获取方法名称
    6 NSString *变量名 = NSStringFromSelector(SEL 参数);
    7 // 通过SEL类型对象,获取到此方法的方法名称
    8 NSString *变量名 = [SEL methodname];
  • 调用方式

    1 // 对象 -- 接收器
    2 [对象 performSelector: SEL类型变量 withObject: 参数1 withObject: 参数2 ...];
  • 好处:增加其方法使用的灵活性,可以通过配置文件(文本文件、XML文件)指定程序要执行的方法,在runtime读取配置文件,将方法名称或方法名称字符串转换成SEL类型对象,通过发送消息执行。由于,OC中寻找方法是通过ID(一个整型值),相比匹配字符串寻找方法要有效率得多。

四、函数指针

  • 格式

    1 // C函数指针,id -- 接收者对象,SEL -- 方法的SEL类型对象,NSString * -- 方法参数(自定义)
    2 void (*func)(id, SEL, NSString *);
    3 // OC
    4 IMP funoc;

    PS: 用法和C一样。

  • 例子

    1 id cla = [[ClassE alloc] init];
    2 SEL funoc = @Selector(fun);
    3 void (*func)(id, SEL, NSString *);
    4 func = (id, SEL, NSString *) [cla methodForSelector: funoc];
    5 func(cla, funoc, @"test");
  • 参数 (在OC中,函数指针的前两个参数,即:id与SEL是必须的,剩下的参数是由函数指针的参数序列决定)

      1. id -- 是一个id类型,是指消息的接收者对象。在runtime实际上id就是self对象,因为要从某个对象发送消息。
      2. SEL -- 是一个SEL类型,是指方法的ID(方法的身份证明,一个整型),在消息发送过程中,通过_cmd方法本身的SEL(方法ID)。也就是说在方法的定义体里面,可以通过_cmd获取方法本身的ID。
      3. NSString* -- 自定义参数。
时间: 2024-10-12 02:42:16

Class 类型、Selector 选择器、SEL 类型、函数指针的相关文章

typedef 返回类型(*Function)(参数表) ——typedef函数指针

//首先看一下函数指针怎么用 #include <iostream> using namespace std; //定义一个函数指针pFUN,它指向一个返回类型为char,有一个整型的参数的函数 char (*pFun)(int); //定义一个返回类型为char,参数为int的函数 //从指针层面上理解该函数,即函数的函数名实际上是一个指针, //该指针指向函数在内存中的首地址 char glFun(int a) { return (char)a; } int main() { //将函数g

objective-c中的@selector()和 c /c++的函数指针

先看tomcat里用到的代码: //然后开始动画 //把图片放到animationImages,接受数组参数 self.tom.animationImages = arrayImage; //设置时间间隔,81张图,图多就播的时间稍微长,否则短 self.tom.animationDuration = arrayImage.count * 0.074; //设置重复次数 self.tom.animationRepeatCount = 1; //开始动画 [self.tom startAnimat

数组指针、指针数组、函数指针、指针函数 -----笔记

1.数组的四种访问方式 定义数组 a[]; 指针 *p 指向数组a; (1) 利用数组的下表进行访问 a[i]; (2) 数组名+地址的偏移量i *(a+i) (3) 利用指针 p 进行下表访问 p[i] (4) 指针p + 地址的偏移量i *(p+i) 一维数组数组名:相当于一个单指针 2. 数组指针(指针)     指针数组(数组) 函数指针(指针)     指针函数(函数)    -------->只看后边两个字就能够区分是指针还是数组或函数 _______________________

恼人的函数指针(二)

原文链接:http://www.cnblogs.com/AnnieKim/archive/2011/12/04/2275589.html 前面曾写过一篇恼人的函数指针(一),总结了普通函数指针的声明.定义以及调用,还有函数指针数组,函数指针用作返回值等.但是作为C++的研读,我发现我漏掉了一个最重要的内容,就是指向类成员的指针,这里将做相应补充(相关代码测试环境为vs 2010). 指向类成员的指针总的来讲可以分为两大类四小类(指向数据成员还是成员函数,指向普通成员还是静态成员),下面一一做介绍

Scheme中lambda表达式与函数指针小例

SICP/Chapter2/Exercise-2.4 Lambda表达式语法 (lambda kw-formals body) 题目描述 用过程性表示方式重写序对的cons.car.cdr Scheme代码 (define (cons-24 x y) (lambda (m) (m x y))) (define (car-24 z) (z (lambda (p q) p))) 这段代码只有4行,但是逻辑关系并不好理解. 原因在于函数式语言的自顶向下实现方式不符合一般的逻辑习惯. lambda以类似

Delphi函数指针的两种定义(对象方法存在一个隐藏参数self,所以不能相互赋值)

delphi中经常见到以下两种定义 Type TMouseProc = procedure (X,Y:integer); TMouseEvent = procedure (X,Y:integer) of Object; 两者样子差不多但实际意义却不一样, TMouseProc只是单一的函数指针类型; TMouseEvent是对象的函数指针,也就是对象/类的函数/方法 区别在于类方法存在一个隐藏参数self,也就是说两者形参不一样,所以不能相互转换 这也就是为什么delphi中可以这样赋值 but

函数指针,function,bind, lambda

函数指针,sd::function<type1, type2...> functionObject, std::bind() 1. 函数指针是类型不安全的,为什么? #include<stdio.h> int max(int x,int y){return (x>y? x:y);} int main() { int (*ptr)(int, int); int a, b, c; ptr = max; scanf("%d%d", &a, &b)

Delphi(procedure&amp;procedure .... of object )函数指针与方法指针 .

Delphi(procedure&procedure .... of object )函数指针与方法指针 . delphiobjectbuttonintegerdelphi中经常见到以下两种定义 Type TMouseProc = procedure (X,Y:integer); TMouseEvent = procedure (X,Y:integer) of Object; 两者样子差不多但实际意义却不一样, TMouseProc只是单一的函数指针类型; TMouseEvent是对象的函数指针

函数指针,函数指针数组,函数返回值为函数指针

函数的名字就是函数的首地址:定义函数指针; int (*p)(int ) p为函数指针变量名字,int 为函数的返回值类型为int型:(int)为函数的形参类型为int型, 注:因为优先级所以要用(*p),否则就会p先和后面的()结合为int*p(int),意思就变为p(int)函数的返回值为int* 注:main2()函数中   int (*p[])(int ,int )  为一维数组,下面写错了, #include<stdio.h> #include<stdlib.h> int