• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

三种语言(c++、as、lua)中函数的差异性

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

对于不同的语言, 尤其是静态语言和动态语言, 对于函数的定义(即如何看待一个函数)和处理截然不同。具体来说可以分为两类:

1、将函数视为第一类型值, 即函数和其他的对象一样, 都是语言中一个普通的对象类型, 如同基本类型int, string。as和lua作为动态语言都可以归为此类。

2、将函数视为非第一类型值, 即函数本身并不是一种类型的对象, 而仅仅是一个定义, 函数名作为入口地址来使用。c++作为静态语言可以归为此类。

 

一、对于函数的this对象处理

1、c++中函数的this只对成员函数有效。成员函数指针的声明也与普通函数指针的声明不同, 必须指定类的定义。

例如,一个类的定义如下


class CAnimal
{
public:
    void printName();              
}

则它的一个成员函数指针可以定义如下:

void (CAnimal::*memberFunc)(void) = &CAnimal::printName;

而要通过成员函数指针来调用一个函数, 则必须通过某个类实例来调用,如下:

CAnimal dog1;
CAnimal dog2; (dog1.
*memberFunc)();  //dog1

(dog2.*memberFunc)();  //dog2

这时候, 编译器会自动将this指向dog对象。

2、as中无论是成员函数还是非成员函数(匿名函数, 也即closer function), 都是可以使用this关键字。区别在于如果用一个Function对象分别指向一个类的实例的成员函数, 则该Function对象在调用时, 无论使用什么方法调用(函数式调用, apply或者call),this对象是不变的, 即初始化时绑定的类实例。而如果用一个Function对象指向一个closer function, 则this指向在调用时显示指定的函数对象。

as要实现1中c++例子的功能, 则需要类似于如下的代码:

public class Animal
{
    public function printName(): void;
}

//绑定成员函数示例
Animal dog1;
Animal dog2;
var memberFunc: Function = dog1.print;
memberFunc();    //dog1
memberFunc.apply(dog2);    //虽然这里显示的指定dog2,但是依然输出dog1.

//绑定闭包函数示例
var closerFunc: Function = function(): void
{
    this.printName();  
};
closerFunc.apply(dog1);    //dog1
closerFunc.apply(dog2);    //dog2

实际上我个人认为, 在闭包函数中使用this, 是一个相当不好的习惯。因为闭包函数本身是一个临时函数, 不属于任何对象。 如果说要作用于某个对象, 还不如把这个对象设置为函数参数。基于这个观点, 我实在看不出在as3.0里, Function的apply和call中的第一个参数thisArg有任何存在的价值。

3、lua中的self即是this的概念。lua是通过语法糖:定义函数时来自动获取self对象的。 如果是通过一个function对象来调用函数, 则self永远是不固定的, 必须在调用时显示的传入第一个参数作为self。

CAnimal = {};

function CAnimal:new(o)
--省略
end

function CAnimal:printName()
    print("name: ", self._name);
end

local dog1 = CAnimal.new();
local dog2 = CAnimal.new();

local memberFunc = CAnimal.printName;    --这里也可以直接写成local memberFunc = dog1.printName;

memberFunc(dog1);    --dog1
memberFunc(dog2);    --dog2


二、关于同一个类不同实例的函数对象或者说函数指针的相等比较

1、C++中的函数并非是一个类型值, 而是一个地址, 并且只能通过函数指针进行存储。所以不存在同一个类不同实例的函数指针比较的说法, 他们的同一个成员函数永远指向同一个地址。

2、as中同一个类不同实例的函数对象是不等的,如:

dog1.printName != dog2.printName;    //true

3、lua的设计实际上是没有类和实例的概念, 而是通过类的原型和类的实例来模拟oo系统。在上面的例子也可以看到, 不同实例的同一个函数实际上是原型的同一个属性。所以可以认为同一个类不同实例的函数对象是相等的, 如:

dog1.printName == dog2.printName;    --true

 4、C++、as、lua对于闭包函数的比较是相同的, 同一个闭包函数是相等的, 非同一个闭包函数是不相等的。这里要特别注意理解同一个闭包函数的意义, 即第一次赋值定义, 如:

function getHandler(): Function
{
    return function():void
    {
        //省略
    };
};

var handler1: Function = getHandler();
var handler2: Function = handler1;
var handler3: Function = getHandler();

trace(handler1 == handler2);    //true;
trace(handler1 == handler3);    //false;

 三、在c++和lua中实现一套灵活的消息机制

  上面对不同的语言的函数特性进行了较为深入的分析和比较, 接下来为了在以C++为宿主语言(我们也不妨称之内核),以lua为逻辑脚本语言的程序架构中实现一套灵活好用的消息机制, 我们首先将逻辑层面的消息模型表示出来,然后再根据语言特性采用合理的方式来实现这个抽象模型。

  as中的事件模型, 是以IEventDispather为基础的,每一个EventDispather的派生类都可以利用系统已有的机制, 增加事件监听对象以及派发事件。尤其需要注意的是, 显示列表中的对象的事件模型, 被划分为三个阶段:捕获阶段包括从根到事件目标节点之前的最后一个节点的行程,目标阶段仅包括事件目标节点,冒泡阶段包括到显示列表的根的回程上遇到的任何后续节点。如果把as的事件模型看做一个典型的观察者模式, 则每一个EventDispather都是一个被观察的subject, 而他的一个事件监听对象便是一个observer的一个回调接口(这里为什么说是一个回调接口,而不是一个observer。因为一个observer会对一个object注册多个监听接口。而as中Function最方便的地方是不仅确定了回调接口, 而且可以方便的进行相等比较, 还唯一对应一个对象实例。具体可以参考), 用于响应一个特定的事件。

  为as定制的mvc框架robotlegs。()


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Lua中的weak表——weaktable发布时间:2022-07-22
下一篇:
cocos2d-lua消除游戏实战(一)主场景和游戏场景设计发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap