类型转换
创建数字符
有必要把一组数字类型变化成另一种数字类型,但并非作用数字类型都能转换,下面是允许转换的模式:

箭头指明表示转换方向,期间没有任何损失信息,布尔型可以取代字符类型(只占用1字节),颜色型可以取代整型(4字节),日期时间型可以取代长型(占用8字节)。四条灰色虚线,也带有箭头,在精确度缺失时,表示转化。例如,与123456789相等的整数字 (int) 就高于浮点型 表示的数字。
int n=123456789;
float f=n; // f 内容同于 1.234567892E8
Print("n = ",n," f = ",f);
// 结果 n= 123456789 f= 123456792.00000
|
转化成浮点型的数字有同样的命令,但是精确度比较低。与黑色箭头不同的是,转化允许部分数据丢失。字符型和无符号字符型间的转化,短整型和无符号短整型间的转化,整型及无符号整型的转化,长整型和无符号长整型的转化(双向转化),都可能导致数据丢失。
因此浮点值转化成整数型的结果就是,经常删除小数部分。如果想把浮点转成最近的整数(任何情况下都很有用),应该使用 MathRound() 。
示例:
//--- 重力加速度
double g=9.8;
double round_g=(int)g;
double math_round_g=MathRound(g);
Print("round_g = ",round_g);
Print("math_round_g = ",math_round_g);
/*
Result:
round_g = 9
math_round_g = 10
*/
|
如果用二进制合并两个值,执行操作前,需要按照下表的先后顺序,把低类型转化成高类型。

数字类型字符型,无符号字符型,短整型,和无符号短整型,无条件的转化成整型。
示例:
char c1=3;
//--- 第一示例
double d2=c1/2+0.3;
Print("c1/2 + 0.3 = ",d2);
// 结果: c1/2+0.3 = 1.3
//--- 第二示例
d2=c1/2.0+0.3;
Print("c1/2.0 + 0.3 = ",d2);
// 结果: c1/2.0+0.3 = 1.8
|
计算的表达式由两种操作构成。示例一,字符型变量c1转化成整型临时变量,因为除法操作中的第二运算对象,常量2,是高类型整型。因此3/2的整数我们取整数值,1。
在示例一中的第二步中,第二运算对象是常量0.3,双精度型,那么结果就是第一运算对象转化成1.0双精度型临时变量。
示例二中,字符型c1变量转化成双精度型临时变量,因为除法操作的第二运算对象,常量2.0,是双精度型;无进一步转化。
数型类型转换
在MQL5语言表达式中,使用明确和含蓄两种类型转换。明确类型转换如下:
表达式或者函数执行的结果可用作 var_2变量。明确类型转换的函数记录也可以如此:
基于第一示例,考虑下明确类型转换。
//--- 第三示例
double d2=(double)c1/2+0.3;
Print("(double)c1/2 + 0.3 = ",d2);
// 结果: (双精度)c1/2+0.3 = 1.80000000
|
做除法前,c1变量明确为双精度型。现在整型常量2,转换成双精度型2.0,因为转换造成第一运算对象成为双精度型。实际上,明确类型转换时是一种一元运算操作。
此外,当尝试转换类型时,结果可能超出允许范围内。在这个情况下,容易发生截断。例如:
char c;
uchar u;
c=400;
u=400;
Print("c = ",c); // 结果 c=-112
Print("u = ",u); // 结果 u=144
|
在运算完成之前(除了数据已被定义的),数据会根据优先级被转换。当定义数据的操作完成前,数据会转换成被定义的数据类型。
示例:
int i=1/2; // 无类型转换, 结果是 0
Print("i = 1/2 ",i);
int k=1/2.0; // 表达式转换到双精度型,
Print("k = 1/2 ",k); // 那么就是到整型的目标类型,结果是0
double d=1.0/2.0; // 无类型转换,结果是 0.5
Print("d = 1/2.0; ",d);
double e=1/2.0; // 表达式转换到双精度型,
Print("e = 1/2.0; ",e);// 同于目标类型,结果为0.5
double x=1/2; // 整型表达式转换到双精度目标类型,
Print("x = 1/2; ",x); // 结果是 0.0
|
如果整型值大于9223372036854774784或小于-9223372036854774784,当从长整型/无符号长整型转化到双精度型时,精度可能会丢失。
void OnStart()
{
long l_max=LONG_MAX;
long l_min=LONG_MIN+1;
//--- 定义最高整型值,在转换到双精度时不会丢失精度。
while(l_max!=long((double)l_max))
l_max--;
//--- 定义最低整型值,在转换到双精度时不会丢失精度。
while(l_min!=long((double)l_min))
l_min++;
//--- 派生发现的整型值区间
PrintFormat("When casting an integer value to double, it must be "
"within [%I64d, %I64d] interval",l_min,l_max);
//--- 现在,让我们看看如果值跌落该区间会发生什么
PrintFormat("l_max+1=%I64d, double(l_max+1)=%.f, ulong(double(l_max+1))=%I64d",
l_max+1,double(l_max+1),long(double(l_max+1)));
PrintFormat("l_min-1=%I64d, double(l_min-1)=%.f, ulong(double(l_min-1))=%I64d",
l_min-1,double(l_min-1),long(double(l_min-1)));
//--- 收到下面结果
// 当将整型值转换到双精度型时,它应该在[-9223372036854774784, 9223372036854774784]区间。
// l_max+1=9223372036854774785, double(l_max+1)=9223372036854774800, ulong(double(l_max+1))=9223372036854774784
// l_min-1=-9223372036854774785, double(l_min-1)=-9223372036854774800, ulong(double(l_min-1))=-9223372036854774784
}
|
字符串类型转换
字符串类型是几种简单类型中的最高级别。因此,如果操作的运算对象之一为字符串,第二运算对象自动转换成字符串。注意的是,对于字符串,添加独立二元操作是可以的。允许任何字符串明确转换成数字类型。
示例:
string s1=1.0/8; // 表达式转换到双精度型,
Print("s1 = 1.0/8; ",s1); // 那么就是到字符串的目标类型,
// 结果 is "0.12500000" (包括10个字符的字符串)
string s2=NULL; // 字符串无法初始化
Print("s2 = NULL; ",s2); // 结果是空值字符串
string s3="Ticket N"+12345; // 表达式转换到字符串类型
Print("s3 = \"Ticket N\"+12345",s3);
string str1="true";
string str2="0,255,0";
string str3="2009.06.01";
string str4="1.2345e2";
Print(bool(str1));
Print(color(str2));
Print(datetime(str3));
Print(double(str4));
|
基本类指针到派生类指针的类型转换
打开生成分类目标也可以看做相关基本类目标。这将导致一些有趣的影响。例如,即使一个基本类生成的不同类目标彼此明显不同,我们仍然可以创建它们的链接列表(List),因为我们将它们全部视为基本类型的目标。但是反过来却不可以:基本类目标不能自动成为派生类的目标。
您可以使用明确转换,将基本类指针转化成派生类指针。但是对这种转化要有足够的资格,因为否则的话,会导致危险的运行错误而mql5程序会停止。
动态类型转换使用 dynamic_cast 操作符 #
动态类型转换使用仅能用于指针到类的dynamic_cast操作符来执行。在运行时完成类型验证。这意味着使用dynamic_cast操作符时编译器不会检查应用于类型转换的数据类型。如果指针转换到一个并不是实际对象类型的数据类型,那么结果为NULL。
dynamic_cast <type-id> ( expression )
|
尖括号中的 type-id 参数应该指向之前定义的类类型。不同于 C++,表达式 操作数类型可以是除了void以外的任何值。
例如:
class CBar { };
class CFoo : public CBar { };
void OnStart()
{
CBar bar;
//--- 允许动态转换* bar 指针类型 * foo 指针
CFoo *foo = dynamic_cast<CFoo *>(&bar); // 不重要的错误
Print(foo); // foo=NULL
//--- 禁止尝试引用Foo 类型对象明确转换Bar 类型对象
foo=(CFoo *)&bar; // 关键的运行时间错误
Print(foo); // 这个字符串不被执行
}
|
另见
数据类型