Ada:子类型转换或调用'Base

5

我有一个简单的问题:用delta类型表示度数,其中一个子类型是角度,我将其范围限制在0.0 .. <360.0之间。 现在,我想覆盖子类型的“+”运算符,以使用自己的模运算符:

package ...
type Degree is digits Degree_Digits;
end package

package ...
subtype Limited_Angle is Degree range Degree_Min .. Degree_Max;
function "+" (Left, Right : in Limited_Angle) return Limited_Angle;
end package

实现方法:

function "+" (Left, Right : in Limited_Angle) return Limited_Angle is
    res : Degree;
begin
    res := Units.Base.Degrees."+"(Left, Right);
    ...
    return Limited_Angle(res);
end "+";

但我不喜欢这种方式,使用+-运算符进行调用。我的第一个想法是使用类似于

的方式:
res := Degree(Left) + Degree(Right);

但是这个方法不起作用。我的编译器警告有无限递归的问题。 即使更加严格:
res := (Degree(Left)) + (Degree(Right));

这是有关无限递归的警告。我不理解其原理。T(S)不应该将S转换为T吗?它不能是优化问题,因为(T(S))也不起作用。

我是否误解了类型-子类型转换的概念(很可能),有人有解决方案/解释吗?或者甚至有更好的解决方案?

谢谢!

2个回答

5
您的问题与类型转换无关,而是与类型和子类型之间的区别理解有关。
所有类型的子类型具有完全相同的操作。类型的子类型之间的差异(包括类型本身,技术上是“类型的第一个子类型”)仅在于允许的值集合。
这意味着您在DegreesLimited_Degrees之间进行的所有转换都没有什么作用,而您对Units.Base.Degrees."+" (Left, Right)的调用实际上是一个递归调用。
我认为解决您的问题的方法是将Limited_Degrees作为派生类型而不是子类型。

0

目前没有可用的编译器,因此尚未经过测试,但是

res := Units.Base.Degrees."+"(Left, Right);

有点可疑,因为您不应该需要为leftright指定运算符"+",它们是Limited_Angle。所以我想知道上面的行是否调用了当前的"+"运算符(因此是递归的)?

我会尝试写成:

function "+" (Left, Right : in Degree) return Limited_Angle 

这是更好的选择,因为您可以在模数之前使用"+"数学运算以Degree为单位。这样还可以节省调用时的转换。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接