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