这是昨天开发中遇到的另外一个平台相关小问题。见代码如下:
typedef Request = { var code: Int; var data: String; }
public function request(?requestCode: Int = 1, ?requestData: String) {
var requestList: Array<Request> = [];
requestList.push({ code: requestCode, data: requestData });
...
}
这段代码在Flash目标上可正确构建,但在CPP目标上(准确的说是Windows目标)却出错,而且不是haXe构建出错,而是haXe生成的CPP代码的编译错误,错误信息是无法把Dynamic转换为&Int,找到release目录中haXe生成的CPP代码中的对应位置,发现是上面的代码中requestList.push那行中,code: requestCode赋值的问题,但是那里并没有Dynamic啊,requestCode应该是Int型啊?真是奇怪。
深入的想了想,终于理解了这个问题。这里就要谈到haXe的一个很有趣也很实用的语言特性了,那就是haXe的基本数值类型Int, Float是允许为空的,这个特性有时很实用,比如你可以用null来表示一种特殊情况,尤其是上面的代码中作为函数的默认参数时,这样是很方便的,这里haXe的Int更像是java中的Integer对象。
那面上面的代码构建错误说明了什么呢?
我的分析是:
1. 函数的可选参数,以及可为空的基本类型比如Null<Int>, Null<Float>,实际上是作为Dynamic类型的。即使上面的代码中指定了默认值为1也并不影响编译器对类型的选择
2. 从生成的c++目标代码中来看,对于声明为Int的变量,在c++中则是直接用基本类型Int的,从而保证很高的性能
3. 这样一来,上面出错的那一行,试图把Null<Int>赋值给Int,就导致了CPP编译出错
既然找到了问题,那么在我的代码中修正就很简单了,不必多说。
这严格说是haXe编译器的hxcpp后端问题,从合法的haXe代码生成出了不合法的c++代码,这确实是bug。希望以后haXe对这类问题至少要有编译期警告,否则平台的不一致行为导致此类问题难于定位。
又是一个平台差异性问题,这里仅做记载。