Ada 编程/属性/'Base
表示另一个类型或子类型的基类型。此属性用于访问基类型的属性。
T'Base 指的是类型的“基范围”,它定义了中间计算执行的范围。
标准规定 T'Base 的范围
- 包括值 0
- 关于零对称,可能有一个额外的负值
- 包括子类型 T 中的所有值
例如,如果 T 是
typeTisrange1 .. 42;
那么编译器将选择一个包含此范围的硬件支持类型,在本例中可能是八位类型(在二进制补码机器上)
typeT'Baseisrange-128 .. 127;
此定义不应被理解为字面意思,因为根据 Ada 语义,T 和 T'Base 不兼容。实际上,T 的声明将是
subtypeTisT'Baserange1 .. 42;
请注意,内置运算符通过基类型执行,例如 T 的“+”运算符被隐式声明为
function"+" (L, R : T'Base)returnT'Base;
T'Base 上没有约束检查,例如
declareO1 : T := T'(1) + T'(2); O2 : T'Base := T'(1) + T'(2);begin
那么在对 O1 的第一次赋值中,有一个约束检查以确保 1 + 2 的结果在 T 的范围内,但在对 O2 的第二次赋值中,没有检查。
T'Base 对泛型很有用,当你需要能够恢复类型的基范围时,以便声明一个值为 0 的对象;例如,如果这是一个累加器。
了解类型的基范围是有帮助的,这样你就能保证在中间计算中不会发生溢出。例如,给定上面的类型 T,那么
procedureOp (O1, O2 : T)isSum : T'Base := O1 + O2;begin
这是一个问题,因为如果 O1 和 O2 的总和很大(即大于 T'Base'Last),那么就会发生溢出。知道要将两个值加在一起意味着你应该以这种方式声明类型
T_Last :constant:= 42;typeT_Baseis0 .. 2 * T_Last;subtypeTisT_Baserange1 .. T_Last;
这样你就知道(子)类型 T 的范围是 1 .. 42,但你也保证 T'Base'Last >= 84,因此两个类型 T 的值的总和不会溢出。
请注意,以下形式的声明
typeTisrange...
实际上声明了一个名为 T 的子类型,它属于某个匿名基类型。我们可以将此基类型的范围称为 T'Base。
枚举类型是它自己的基类型,因此给定此类型
typeETis(A, B, C);
那么 ET 的范围与 ET'Base 的范围相同。如果你在你的“基”类型中需要一些额外的文字,那么你必须手动声明它们,这与我们上面所做的类似
typeET_Baseis(ET_Base_First, A, B, C, ET_Base_Last);subtypeETisET_BaserangeA .. C;
现在你可以说 ET'Succ (ET'Last),你将得到一个有意义的答案。这在执行以下操作时是必需的
declareE : ET'Base := ET'First;beginwhileE <= ET'Lastloop... -- do something E := ET'Succ (E);endloop;end;
同样,当你从 ET_Base 派生并使用范围约束时,派生类型的基类型将包含基类型的所有值
typeNew_ETisnewET_BaserangeA .. C; Correct:constantBoolean := New_ET'Base'First = ET_Base_First;
请注意,这里 ET_BASE_First 的类型为 New_ET。
如果你声明
typeMy_Enumis(Enum1, Enum2, Enum3);
并且
subtypeSub_EnumisMy_EnumrangeEnum1 .. Enum2;
那么Sub_Enum'Base'Last是Enum3.
