ADA程序实例(运算符重载)

ADA支持对几乎它自身的所有运算符的重载,虽然ADA的运算符系统不像C/C++那样庞大灵活,ADA提供这种重载某种意义上说是为了达到作为对象操作的一致性要求,这也理应是运算符重载的目的。由于ADA本身的运算符定义特征,所有运算符都是单目或双目的,而ADA将他们均看成函数(function),其参数是输入性(in)对象类型,输出是这种对象类型。以下是一般用来阐释运算符重载的经典方法之一,复数的定义和运算。其实ADA本身也提供了复数的泛型模板,但是这里的小例子强调一些ADA的语言特征。比如ADA本身提供的复数泛型只支持数值类型作为复数分量,而这里采用了任何类型。

复数定义文件(complex.ads),这里几点注意:

ADA的泛型参数约束比较复杂,但是个人认为基本上是靠谱的,比PASCAL的类型相容性定义不知要好了多少了。因为它基本描述了ADA中允许的数据定义的种类。这里用了is private,大体上是支持几乎所有的ADA数据类型,关于这些泛型参数约束的说明可参见wikibook的一个表格。由于类型约束很松,所以在泛型参数里还要加上对这个类型用到的运算和方法的指定。在这里是一组运算符(加减乘除和负号)以及一个转换到字符串的函数。这些运算符显然在复数运算中要用到。有意思的是,由于减号和负号的符号是一致的,作为泛型的形参的时候(见在后面complex.adb中实例化)会发生二义性(虽然理论上编译器可以通过函数参数来分辨这个重载,但可能ADA的设计不允许代码中出现这种含糊的情况),所以这里只能用实名函数来代替,随后再用ADA一个很有意思也很强大的renaming特性将他们转化成为运算符,供这个泛型模板的实现中继续用运算符的方式使用它们。这里可见在ADA中,在运算符重载意义上,运算符和函数是没有区别的。

generic
  
  -- the type of the components of the complex number is defined here
  -- as genereic argument delcared as 'private' which basically can 
  -- be almost any ADA type
  type value_t is private;
  
  -- since value_t is declared as 'private', the caller needs to explicitly
  -- provide operators on the type used by this program even if the actual 
  -- type is numerics.
  -- since subtract and minus operations share the same symbol, we might have
  -- to use named function for formal arguments here to differentiate them, 
  -- fortunately we can use ADA's renaming feature to switch them back.
  with function "+" (x, y : value_t) return value_t;
  with function subtract (x, y : value_t) return value_t;
  with function "*" (x, y : value_t) return value_t;
  with function "/" (x, y : value_t) return value_t;
  with function minus(x : value_t) return value_t;
  
  -- function to convert the value to string
  with function to_string(x : value_t) return string;
  
package complex is
  -- renaming for subtract and minus operations
  function "-"(x, y : value_t) return value_t renames subtract;
  function "-"(x: value_t) return value_t renames minus;
  
  -- declaration of the complex object type in the public region
  type object is tagged private;
  
  -- set individual component of a complex
  procedure set_real(obj : in out object; r : value_t);
  procedure set_imag(obj : in out object; i : value_t);
  
  -- get individual component of a complex
  function get_real(obj : in object) return value_t;
  function get_imag(obj : in object) return value_t;
  
  -- operator overloading for complex objects  
  function "+"(obj1, obj2 : in object) return object;
  function "-"(obj1, obj2 : in object) return object;
  function "*"(obj1, obj2 : in object) return object;
  function "/"(obj1, obj2 : in object) return object;
  function "-"(obj : in object) return object;
  
  -- cast to and from string 
  function to_string(obj : in object) return string;
  
private
  
  -- detailed data definition for complex object
  type object is tagged record
    r : value_t;
    i : value_t;
  end record;
  
end complex;

Note that I later realized that the operator as formal generic parameter can be specified in a different way (less ugly than having function-like names) to either

1. look for and make use of existing operators defined on the respective type without having to specify what and where they are (as long as the operator definitions end with box "is <>" which indicates use of default) 

2. use => symbol to explicitly associate formal parameters and actual parameters excluding ambiguous formal parameters (e.g., "-" operators above, o.w., an error saying "name not allowed for overloaded operators" will be given)

3. pass the parameters in the same order as the corresponding formal parameters are defined.


复数的实现文件(complex.adb),从这里可见对分量类型的所有运算符都配置好了,所有只要用加加减减就能成了。
with Ada.Strings.Fixed; use Ada.Strings.Fixed;

package body complex is
  
  -- setters and getters
  
  procedure set_real(obj : in out object; r : value_t) is
  begin
    obj.r := r;
  end set_real;
  
  procedure set_imag(obj : in out object; i : value_t) is
  begin
    obj.i := i;
  end set_imag;
  
  function get_real(obj : in object) return value_t is
  begin
    return obj.r;
  end get_real;
  
  function get_imag(obj : in object) return value_t is
  begin
    return obj.i;
  end get_imag;
    
  -- operator overloading for complex objects  
  
  function "+"(obj1, obj2 : in object) return object is
    result : object;
  begin
    result.r := obj1.r + obj2.r;
    result.i := obj1.i + obj2.i;
    return result;
  end "+";
  
  function "-"(obj1, obj2 : in object) return object is
    result : object;
  begin
    result.r := obj1.r - obj2.r;
    result.i := obj1.i - obj2.i;
    return result;
  end "-";
  
  function "*"(obj1, obj2 : in object) return object is
    result : object;
  begin
    result.r := obj1.r * obj2.r - obj1.i * obj2.i;
    result.i := obj1.r * obj2.i + obj1.i * obj2.r;
    return result;
  end "*";
  
  function "/"(obj1, obj2 : in object) return object is
    q : value_t;
    result : object;
  begin
    q := obj2.r * obj2.r + obj2.i * obj2.i;
    result.r := (obj1.r * obj2.r + obj1.i * obj2.i) / q;
    result.i := (obj1.r * obj2.i - obj1.i * obj2.r) / q;
    return result;
  end "/";
  
  function "-"(obj : in object) return object is
    result : object;
  begin
    result.r := -obj.r;
    result.i := -obj.i;
    return result;
  end "-";

  -- conversion from complex object to the string that represents it
  function to_string(obj : in object) return string is
    result_str : string(1..32) := 32 * " ";
  begin
    result_str := overwrite(result_str, 1, 
                            to_string(obj.r) & to_string(obj.i) & 'j');
    return result_str;
  end;
    
end complex;

示例主程序(operatorsdemo.adb),在这里的泛型模板的实例化中要对这些形参赋予实际的内容,可见这里的运算符实参就是float运算符本身,(目前为止至少没有发现)而这些运算符估计是系统内建而不依赖于任何package的。

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
use Ada.Strings;
with complex;

procedure operatorsdemo is
  
  function float_to_string(value : float) return string is
  begin
    return Trim(float'Image(value), Both);
  end float_to_string;
    
  package float_complex is new complex(value_t=>float, "+"=>"+", 
                                       subtract=>"-", minus=>"-",
                                       "*"=>"*", "/"=>"/", 
                                       to_string=>float_to_string);
  use float_complex;
  
  c1, c2, c : float_complex.object; 
  
begin
  Put_Line("Operators Overloading Demo");
  
  c1.set_real(3.0);
  c1.set_imag(4.0);
  c2.set_real(5.0);
  c2.set_imag(6.0);
  
  c := c1 * (-c2);
  
  Put("c = c1 * c2 = ");
  Put_Line(c.to_string);
  
end operatorsdemo;
保留原有所有功能,新增直接从mapinfo图层输出googleearth kml文件的工具。 Mapinfo 2 Googleearth 将ADA_CDMATool基础上生成的CDMA_Cell_Map_NB图层直接转为googleearth的kml文件。 kml保留扇区的三叶草图形,全向站用六边形标识。 ///////原有功能///////// ADA CDMA Tool Help 扇区信息表格式 扇区信息表:CdmaCellInfo.xls。 “Bearing”列为方位角,“radius”列为半径,“FREQ”列为不同频率,“H_BeamWidth”为扇区水平瓣宽,“Longitude”经度,“Latitude”纬度。 “扇区类型”列用“射频拉远”标识是否RRU站。 “基站名”列标识站名或者射频拉远站的施主站名。 “物理地址”列标识实际站点站名。 “NeighborNumber”列保存对应扇区的邻小区数。 “N01”记录第一个邻小区的小区号,必须放在第24列。 Make Cell 用来生成扇区结构的mapinfo图层,用不同的方位角和半径来区分同一物理地址不同频点的扇区。 扇区信息表:CdmaCellInfo.xls,放在和本插件同一目录下。 并在同一目录下生成图层CDMA_Cell_Map_NB。 下图即为生成的基站扇区图,圆形为全向站(包括室分系统) 注:以下所有的工具均需要在生成的CDMA_Cell_Map_NB图层上工作! RRU Line 用来生成RRU站和施主站之间的连线。 用箭头工具点击扇区,如果扇区是RRU站则画出其与施主站之间的连线。 用RECT工具进行区域选择,程序会将区域范围内的RRU站与施主站之间连线。 Draw RRU Line all 一次性生成CDMA_Cell_Map_NB图层中所有RRU站与其施主站间的连线。 注:生成全网的RRU联线,所需时间较长。 Find PN 用来查找CDMA_Cell_Map_NB图层中所有指定PN的扇区,填充颜色并标注PN。 可以用此来检查PN复用距离。 下图为find PN 274的结果,标注PN 274 并红色填充对应扇区。 NB Check 显示所选择扇区的所有邻小区并用颜色填充。 可以用此来查看是否有明显的PN漏配。 如果点击选择的位置有多个扇区时,会弹出选择对话框供用户确定扇区。 PN One Way Check 点击图层,输出所点击扇区的邻小区重复PN信息,或者多余邻小区信息(多余邻小区为小区号已经不在现网中)。 注:PN One Way 和 Two way与某一地点的覆盖有很大关系,并不仅仅是邻小区设置的问题,程序中只是检查了基站邻小区的PN是否有重复 PN Two Way Check 检查所点击扇区的邻小区、所有二次邻小区(邻小区的邻小区)之间的PN是否有重复。如果二次邻小区PN重复,则可能存在PN Two way的风险 print出PN Two way点位的Cell信息,在map上连线,显示造成Two way 的邻小区路径。 注:此程序运行时间视邻小区个数与PN重复数有关,在2min~10min左右 注:PN One Way 和 Two way与某一地点的覆盖有很大关系,并不仅仅是邻小区设置的问题,程序中检查了基站邻小区、所有二次邻小区的PN是否有重复 PN Two Way Check 2 检查所点击扇区的邻小区与二次邻小区之间的PN复用关系,不检查二次邻小区之间的复用关系。 用不同的颜色填充和连线显示出可能存在的PN Two Way,此工具检查出来的PN Two Way结果比PN Two Way Check检查出来的结果更有风险。 话统数据分析 选择需要分析的数据列,或者输入需要分析的数据列(输入的列名要与CdmaCellInfo.xls中的列名完全一致),输入分析数据的最大值和5类层级的填充颜色和范围。用不同的颜色标识属于不同范围的扇区,并用图示标识出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值