赋值

使用=可以为左侧表达式赋值,本质是调用了左侧表达式类型的.opAdd()方法

lValue = rValue;
//等同于
lValue.opAdd(rValue);

优先计算右侧的表达式

//rVlue2()较rValue1()优先
lValue = rValue1() + rValue2();

函数调用

函数可以被调用来执行一个动作

func();

函数可能带有一个返回值

int func()
{
    //这个函数返回整数1
    return 1;
}

如果函数使用了多个参数
那么优先从右侧参数开始计算

void func (int arg1, int arg2, int arg3)
{
    //魔法代码
}
//优先计算3+3,其次2+2,最后1+1
func(1+1, 2+2, 3+3);

out参数声明的一些函数以返回多个值。调用这些函数时,必须将输出参数作为可返回值赋值的表达式。
如果不需要输出值,则使用参数void来显式放弃其值

实际上,这并不是传址,只是在函数结束时对表达式再次赋值,AS不存在传址的概念

//这个函数在输出参数中返回一个值
void func(int &out outputValue)
{
    //在函数结束之前,必须对所有有out标记的变量赋值
    outputValue = 42;
}
//调用函数时使用有效的左值表达式来接收函数值
//此时value初始化为0
int value = 0;
//此时value被赋值为42
func(value);
//使用关键词void来显式放弃返回值
func(void);

参数也可以被命名,并且直接传递到特定参数,而不是按照参数的命名顺序传递

位置参数不可以跟随在命名参数后

void function(bool flagA = false; bool flagB = false; bool flagC = false)
{
    //优雅
}
//调用函数时可以通过命名直接传递
function(flagC: true);

运算符

运算符指对变量进行相应操作并返回新值的符号

数学运算符

数学运算符是用来表示数学运算的符号

运算符 描述 左侧 右侧 结果 举例 举例结果
+ 一元正 数字型 数字型 +(-1) 1
一元负 数字型 数字型 -(+1) -1
+ 加法 数字型 数字型 数字型 1+1 2
减法 数字型 数字型 数字型 1-1 0
* 乘法 数字型 数字型 数字型 3*3 9
/ 除法 数字型 数字型 数字型 9/3 3
% 模数 数字型 数字型 数字型 3%2 1
** 指数 数字型 数字型 数字型 3**2 9

加和减也可以用作一元运算符,实际上,他们的符号是完全一样的

数字型可代表任何数字类型,列如intfloat

双操作的左右侧两个变量将会被隐式转化成相同的类型,最终结果与被赋值的变量相同

int imCool;
//2.0f将会被隐式转化为2,最终返回结果为int(1+2) = 3
imCool = 1 + 2.0f;
float imSuperCool;
//1将会被隐式转化为1.0f,最终返回结果为float(1.0f + 2.0f) = 3.0f
imSuperCool = 1 + 2.0f;

一个例外是一元负运算符,不适应于任何无符号类型

//在进行一元运算前变量必须拥有值
uint noSign = 3;
//报错,无符号数不能进行一元负运算
-noSign;

位运算符

位运算符是表示对数字进行位运算的符号

运算符 描述 左侧 右侧 结果 举例 举例结果
~ 按位补 数字型 数字型 ~2 1
& 按位和 数字型 数字型 数字型 2&5 0
| 按位或 数字型 数字型 数字型 2|5 7
^ 按位异或 数字型 数字型 数字型 4^6 2
<< 逻辑左移 数字型 数字型 数字型 2<<5 64
>> 逻辑右移 数字型 数字型 数字型 5>>2 1
>>> 算术右移 数字型 数字型 数字型 8>>>2 2
<<< 算术左移 数字型 数字型 数字型 2<<<8 512

除按位补外均为双操纵符

在进行计算之前,左右侧两个数字都将转化为整数,同时保留原始符号

结果将与左侧数字相同

uint8 leftNum = 4;
float rightNum = 2.0f;
//4将保留无符号整数,2.0f将被隐式转化为有符号整数2进行计算,计算结果将隐式转化为无符号短整数(uint8)类型;
leftNum | rightNum;
//同上,但计算结果将转化为浮点数(float)
rightNum & leftNum;

复合运算符

复合运算符指上述任意运算符与=的组合

//此式首先将leftVal赋值给寄存器,再将1赋值给寄存器,最后将寄存器内数值相加赋值回leftVal
leftVal = leftVal + 1;
//此式将1赋值给寄存器,再将leftVal数值直接与寄存器相加
leftVal += 1;

上述两个式子结果完全一致,而第二个式子将会有更好的运行效率(如果左侧式子本身是复杂的表达式,那么可以有所不同)

可用的复合运算符:
+= -= *= /= %= **= &= |= ^= <<= >>= >>>=

逻辑运算符

逻辑运算符指将两个布尔型量进行运算并放回新布尔值的运算符号

运算符 等同符号 描述 左侧 右侧 结果 举例 举例结果
not ! 逻辑不 布尔型 布尔型 not true false
and && 逻辑与 布尔型 布尔型 布尔型 true and false false
or || 逻辑或 布尔型 布尔型 布尔型 true or false true
xor ^^ 逻辑异或 布尔型 布尔型 布尔型 true xor false true

逻辑运算符多用于ifwhile结构内

if (a and b)
{
    //吃饭
}
else if (b || c)
{
    //睡觉
}
else
{
    //打豆豆
}

比较运算符

等式比较运算符

通过比较两个值数值是否相等从而返回布尔值的运算符

运算符 描述 左侧 右侧 结果 举例 举例结果
== 相等 数字型 数字型 数字型 1 == 2 false
!= 不等 数字型 数字型 数字型 1 != 2 true

关系比较运算符

通过比较两个值数值是否符合关系从而返回布尔值的运算符

运算符 描述 左侧 右侧 结果 举例 举例结果
> 大于 数字型 数字型 数字型 1 > 2 false
< 小于 数字型 数字型 数字型 1 < 2 true
>= 大于或等于 数字型 数字型 数字型 1 >= 1 true
<= 小于或等于 数字型 数字型 数字型 1 <= 2 true

身份比较运算符

引用类型专用运算符(如句柄),比较两个引用对象是否相同

运算符 描述 左侧 右侧 结果 举例 举例结果
is 相等 数字型 数字型 数字型 @a is @a true
!is 不等 数字型 数字型 数字型 @a !is @b true

增量运算符

表达式中使用该值之前或之后以1递增/递减其值的运算符

运算符 描述 左侧 右侧 结果 举例 举例结果
++ 之后增量 数字型 数字型 1++ 2
之后减量 数字型 数字型 1– 0
++ 之前增量 数字型 数字型 ++1 2
之前减量 数字型 数字型 –1 0
//使用增量运算符之前变量必须拥有初始值
int8 value = 0;
//之后增量,首先将value赋值给寄存器,接着在将寄存器数值加一,最后将寄存器赋值回value
value++;//此时value为1
//之前减量,直接在value地址上减一
--value;//此时value为0

索引运算符

用于访问对象内包含的元素的运算符
符号为变量后添加[无符号整数]

array<int> arr = {5,6,7,8};
arr[0]; //5
arr[2]; //7
arr[1337]; //报错,超出数组最大长度
arr[4.2f]; //报错,索引必须为整数
arr[-13]; //报错,索引必须无符号
int i = 2;
arr[i]; //报错,索引必须显式转化为无符号

条件表达式

模板

//条件为真则返回a, 条件为假则返回b
条件 ? a : b;

如果ab不是统一类型,将会进行隐式转换

如果a0null,将会试图将a转化为b类型,否则将b转换为a类型

如果a b之间没有隐式转化方法,将会报错

int a = 0;
float b = 1.0f;
//隐式转换0为0.0f
true ? a : b;

同样,如果a b类型相同,条件表达式还可以用作左值

int a,b;
//将会为b赋值1337
(false ? a : b) = 1337;

成员访问

如果某个对象是一个类型的实例化,那么可通过.符号范围其成员

class CExample
{
    int property;
    void method()
    {
        //做点什么....
    }
}

CExample object;
//property为可get或set的成员
object.property = 1;
//method为可在对象上调用的成员方法
object.method();

句柄

句柄是对对象的引用,多个句柄可以应用同一个对象

使用@符号标识一个句柄对象

当没有任何句柄引用对象时,对象才会销毁(详见AngelScripts 对象句柄文章

通过句柄访问引用对象的方式与直接访问引用对象的方式相同

//声明一个句柄
CExaple@ eHandle;
//句柄引用一个对象
@eHandle = @object;
//通过句柄访问对象, 与object.method()完全相同
eHandle.method();
//清除句柄引用
@eHandle = null;

括号

括号用于标识表达式的运算优先值,括号内外部分将会分别以运算优先表运算(见附录)

//优先计算1+b,再将结果与b相乘
a = b * (1 + b);
//优先计算b或c,再将结果与a相和
if(a && (b || c))
{
    //出事了
}

范围解析

范围解析运算符::,当本地变量或函数与全局变量或函数重载时,指定使用的变量和函数的命名空间的运算符

//命名空间为空时,指全局命名空间
命名空间::变量;

举例

int value; //标记为[0]

namespace NSecret
{
    int value; //标记为[1]
}

void function()
{
    int value; //标记为[2]

    //指[2]被赋值1
    value = 1;
    //指[0]被赋值2
    ::value = 2;
    //指[1]被赋值3
    NSecret::value = 3;
}

类型转换

基础类型转换

不支持对象句柄的基础类型可用强制转换,此时将构造一个新值或创建一个新实例
显式强制转换方法

类型(被转换变量名);
//隐式强制转换
int a = 1.0f;
//显式强制转换
float b = float(a) / 2;

句柄类型转换

可以使用强制转换运算符将对象句柄转换为其他对象句柄。如果强制转换有效,则返回目标类型对象句柄,否则返回空句柄(null)
显式转换方法

cast<目标类型>(句柄对象);
//隐式转换CAmmo句柄为CWeapon句柄
CWeapon @a = @CAmmo();
//显式转换
CAmmo @b;
CWeapon @a = cast<CWeapon@>(b);

通过上述方法转换句柄时,句柄的引用对象和指向的对象并没有变化,只是通过不同的类型公开不同接口

详见AngelScripts 对象句柄文章

匿名对象

匿名对象即未声明为变量而创建的对象

匿名对象可以在表达式中实例化,方法是调用该对象的构造函数,就好像它是一个函数一样

//"Hello World"即是一个匿名字符串对象
g_Game.AlertMessage( at_console, "Hello World" );
//通过构造函数创建一个匿名对象
typeof(CExample());
//字典类显式初始化,此时该字典是一个匿名对象
function(dictionary = {
    {"banana", 1},
    {"orange", 2},
    {"apple", 3}
});
//当只有一种可能类型的初始化列表时,可以省略其类型标记,编译器可以隐式的确定其类型
resortArray({5, 6, 7, 8});

匿名对象使用后即释放,除非有句柄保持了对其的引用


附录:运算优先表

表内越向上者拥有越高的优先级,越向下者拥有越低的优先级

一元运算符

符号 说明 优先级
:: 范围解析 最高
[] 索引
++ — 之后增量
. 成员访问
++ — 之前增量
not 逻辑不
+ – 一元正负
~ 按位补码
@ 句柄 最低

二元与三元运算符

符号 说明 优先级
** 指数 最高
* / % 乘除法和取模
+ – 加减法
<< >> >>> 移位
& 按位和
^ 按位异或
| 按位或
<= < >= > 比较
== != is !is xor ^^ 等值,等身份和逻辑异或
and 逻辑与
or 逻辑或
?: 条件
= += -= *= /= %= **= &= |= ^= <<= >>= >>>= 复合运算 最低
Categories: 教程合集

Dr.Abc

I ❤ Owl

订阅
提醒
guest

0 评论
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x