背景:
阅读文章

LPC基础数据类型--function

[日期:2008-12-25] 来源:  作者: [字体: ]
继续,首先来说明一下已经废止了的call_other方式,
既然call_other被废止了,那么如何定义一个别的物件里面的函数指针变量呢?
答案是用efun型代替,使用 function f = (: call_other, ob, func, arg1, arg2 :)就可以

现在我来用一个例子来说明function的用法,看下面这段代码:

Copy code
int max(int a, int b, int flag);

void create()
{
  int a = 6;
  function f1 = (: max :);
  function f2 = (: max, 2 :);
  function f3 = (: max, 5, 6 :);
  function f4 = (: call_other, this_object(), "max", 8, 2, 1 :);
  function f5 = (: $(a) && ($(clonep() ? a : 8) > $2 ? $1 : $2), 88 :);
  function f6 =
    function(int a, int b, int flag)
    {
        return flag && (a > b ? a : b);
    };
  write(sprintf("%O\n", evaluate(f1, 4, 3, 1)));
  write(sprintf("%O\n", evaluate(f2, 5, 1)));
  write(sprintf("%O\n", evaluate(f3, 1)));
  write(sprintf("%O\n", evaluate(f4)));
  write(sprintf("%O\n", evaluate(f5, 7)));
  a = 0;
  write(sprintf("%O\n", evaluate(f5, 7)));
  write(sprintf("%O\n", evaluate(f6, 9, 8, 7)));
}

int max(int a, int b, int flag)
{
  return flag && (a > b ? a : b);
}


我们来分析一下这段代码
首先第一行声明了一个int型函数,它有三个参数,函数定义在最后后面,之所以提前声明它是为了我们的function变量使用。
进入create函数后,我连续定义了6个function变量
·第一个到第三个都是local function型,不同的是,
第一个没有指定任何一个实参;
第二个指定了第一个实参为2;
第三个制定了第一个实参为5,第二个实参为6;

·第四个是efun型,它指向efun call_other,大家也许发现了,这里的"max"是带双引号的,原因是从this_object()开始(包括this_object())全部都是传递给call_other的参数,而call_other的原型是call_other(物件ob, 字串func, 字串arg1, 字串arg2, ...)(call_other还有其他几个原型,我这里只指明我所使用的这一个),而call_other的作用是呼叫物件ob里面的func函数,arg1, arg2,...都作为参数。所以这个f4是一个执行efun call_other的函数指标,并且把this_object(), "max", 8, 2, 1作为call_other的参数,而call_other呼叫this_object()里面的max函数,并把8, 2, 1作为max的参数。(希望看完这段你没有头晕)

·第五个,这个是表达式(expression)型,为了说明这个表达式的全部特征,我把它写的看起来很复杂,但如果你明白其中的原委就一点也不复杂
作为一个表达式型函数指标变量,在它的内部有这么几个比较特别的地方
$(a)
$(clonep() ? a : 8)
$1
$2
其中$(a)我们解释了是引用外部变量的一个拷贝,$1是第一个参数的拷贝,$2是第二个参数的拷贝
那么$(clonep() ? a : 8)是什么呢?
其实它和$(a)是一回事,整个语法的原型是$(expression),作用是在expression里面有外部变量的时候产生一个它的拷贝,整句和clonep() ? $(a) : 8 没有区别
接着,我把a重新赋值为0,然后再次执行f5,其目的是说明一个特性,$(expression)里面expression的内容是在function变量(这里即f5)被定义的时候就算出来了的,而不是在执行f5的时候才计算,注意这个特性,否则在使用的时候它很可能给你带来一个意外。所以再次执行f5得到的结果并没有因为a的改变而改变。

·第六个就是匿名(anonymous)型函数指标,它书写了一个完整的函数形态,但是它不是一个函数(function是关键字,不是函数名,而且函数内部也是不存在函数的,所以这里说的是函数形态),和expression型比较起来它的功能可能更丰富,但是和local function比较起来它的效率更低,更笨拙,什么时候使用它完全看你的需要。
另外,在这里我还要说明一个特性,就是变量的作用域,在这个匿名函数指标里面我定义了形参int a;而在这个函数create里面我也定义了局部变量int a;你也许很好奇,难道他们不冲突吗?编译的时候不会报错说重复定义吗?
实际上你考虑的问题都不会发生,因为这两个int a作用在不同的域里面,create里面定义的int a在整个函数create里面都起作用,但是对于f6,它是一个匿名函数,它有它的函数体,所以先定义的一个int a在这里就不起作用了,应该说f6里面定义的匿名函数在这个create之外,就好像int max一样,int max里面的 a 和 create 里面的 a 肯定不会出现问题;而且对于匿名型函数指针它也不能像表达式(expression)型函数指针一样通过$(expression)的形式来复制外部变量的拷贝


根据以上的讲解,那么执行这段代码后会得到的结果应该是:
4
5
6
8
88
88
9

把上述保存为一个.c文件,在你的Mud里面update它一下,你会看到结果,看看是不是一样
(以上代码经测试无误)

如果你对function类型变量还有什么不了解的地方,欢迎提出来大家一起讨论。
 
 
收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容      
本文评论   [发表评论]   全部评论 (0)
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论