三种语言(c++、as、lua)中函数的差异性
对于不同的语言, 尤其是静态语言和动态语言, 对于函数的定义(即如何看待一个函数)和处理截然不同。具体来说可以分为两类:
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。()
三种语言(c++、as、lua)中函数的差异性的更多相关文章
- java php c# 三种语言的AES加密互转
java php c# 三种语言的AES加密互转 最近做的项目中有一个领取优惠券的功能,项目是用php写得,不得不佩服,php自带的方法简洁而又方便好用.项目是为平台为其他公司发放优惠券,结果很囧的是 ...
- 树的三种DFS策略(前序、中序、后序)遍历
之前刷leetcode的时候,知道求排列组合都需要深度优先搜索(DFS), 那么前序.中序.后序遍历是什么鬼,一直傻傻的分不清楚.直到后来才知道,原来它们只是DFS的三种不同策略. N = Node( ...
- 进程,多进程,进程与程序的区别,程序运行的三种状态,multiprocessing模块中的Process功能,和join函数,和其他属性,僵尸与孤儿进程
1.进程 什么是进程: 一个正在被运行的程序就称之为进程,是程序具体执行的过程,是一种抽象概念,进程来自操作系统 2.多进程 多个正在运行的程序 在python中实现多线程的方法 from mult ...
- GOF提出的23种设计模式是哪些 设计模式有创建形、行为形、结构形三种类别 常用的Javascript中常用设计模式的其中17种 详解设计模式六大原则
20151218mark 延伸扩展: -设计模式在很多语言PHP.JAVA.C#.C++.JS等都有各自的使用,但原理是相同的,比如JS常用的Javascript设计模式 -详解设计模式六大原则 设计 ...
- 一种C#泛型方法在lua中表示的设计
在进行lua方法注册的时候, 大多数解决方案直接否定了泛型方法, 因为在lua侧难以表达出泛型, 以及lua的函数重载问题, 函数重载问题可以通过一些特殊方法解决, 而泛型问题是主要问题, 以Unit ...
- Hibernate中对象的三种状态以及Session类中saveOrUpdate方法与merge方法的区别
首先,用一张图说明一个对象,在Hibernate中,在调用了不同方法之后对象所处的不同状态 在Hibernate中,一个对象的状态可以被分为如图所示的三种 Transient:瞬时对象,该对象在数据库 ...
- eclipse安装插件的方式 三种:links、eclipse中使用插件安装向导安装、直接copy插件到对应的eclipse目录 MyEclipse10安装SVN插件
myeclipse安装插件 1.直接将插件copy到myeclipse目录下的dropins目录下(没有目录就新建一个),重启,详细参考 MyEclipse使用总结——MyEclipse10安装SVN ...
- ASP.NET Core端点路由中三种让人困惑的路由函数
早先提及了端点路由app.UseEndpoints, 端点路由强调的是端点和 路由,其核心目的是将 请求落地点与路由寻址方式解耦. 这里面有几个容易混淆的函数 MapControllerRoute M ...
- django入门与实践 - 关于升级到django 3.7,三种模板超链接配置(编辑中)
第一种方法: 在myblog/urls.py模块中: from django.contrib import admin from django.urls import path, include ur ...
随机推荐
- #define用法集锦
Definition: The #define Directive You can use the #define directive to give a meaningful name to a c ...
- uafxcwd.lib(afxmem.obj) : error LNK2005 解决方法
项目为非MFC,但要用到MFC的库,使用过程中遇到的问题总结一下 uafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl opera ...
- FZU 2148 Moon Game
Moon Game Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit St ...
- vim使用札记
最近开始用vim编辑器了,从最开始的配置到现在慢慢使用,我在这儿会贴出一些我的使用上遇到过的问题和如何解决的方案,留给自己和一些会用到的人看看 1.vim怎么使汇编语法高亮 开始不知道,然后把文件的后 ...
- ettercap
作者: 官网:http://ettercap.github.io/ettercap/ 源码:https://github.com/Ettercap/ettercap 功能:arp欺骗
- [SAP ABAP开发技术总结]以二进制、字符模式下载文件
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- CUBRID学习笔记 5 错误码
服务器错误码 AS Error Code Number CAS Error Code Error Message Note -1000 CAS_ER_DBMS "CUBRID DBMS Er ...
- ubuntu14.04换一个更快的源
mirrors.yun-idc.com,这个源可比ubuntu自带的源快多了,我的source.list文件内容如下: deb http://mirrors.yun-idc.com/ubuntu/ t ...
- 随机步法A-Z
程序是生成一个10X10的字符数组,初始化时全为 ‘.’ 的随机步法.程序必须随机的从一个元素 ‘走到’ 另一个元素,每次只向上.向下.向左或向右移动一个元素位置.已访问过的元素按访问顺序用字母A到 ...
- hdu 3934&&poj 2079 (凸包+旋转卡壳+求最大三角形面积)
链接:http://poj.org/problem?id=2079 Triangle Time Limit: 3000MS Memory Limit: 30000K Total Submissio ...