Ada子程序的调用
调用子程序(Calling Subprograms)
调用子程序最简单的方式就是按照子程序声明的格式调用,如前例的procedure swap(A:Integer;B:Integer),只要填入的参数是Integer类型,便能直接使用 swap (A,B)。注意调用子程序时参数之间用“,”隔开;同类型的参数在声明时也可简化,如procedure swap(A,B:Integer)。但使用参数时还有下列几种特殊情况.
有名参数(Named Parameter)
我们也可以不按照参数顺序调用子程序。如调用 swap 也可以这样: swap(B => Y, A => X),这时是使用有名参数,明确声明每个变量的值,可以不按照子程序声明中的参数顺序赋值。这样的做的话可读性是好了一点,比较适合参数较多的情况。
如果将有名参数和位置参数一起混用,只需遵守一条规则:位置参数在有名参数前面。因此 swap 的调用有以下几种情况:
swap(x , y);
swap(A => x , B => y);
swap(B => y , A => x);
swap(x, B => Y);
上述四种情况是一样的。下列两种情况是非法的:
swap(y, A => x);---不合法
swap(A => x , y); ---不合法
默认参数值(Default Parameter Values )
在声明某个子程序时,我们也可以使参数具有默认值,如下例:
000 -- filename:putlines.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure putlines is
004 procedure putline(lines: integer:=1) is<> 005 begin
006 for count in 1..lines loop
007 New_Line;
008 end loop;
009 end putline;
010 Line :Integer;
011 begin
012 Put ("Print Lines :"); Get (Line);
013 putline;
014 end putlines;
实际上[012]可有可无,因为调用输出行函数 putline 时,没用参数。而 putline 在声明时赋予了参数 lines 一个默认值 1,这样的话如果调用 putline 没用参数,就以 1 作为参数值。上例也就只输出一个空行。如果putline有参数,如putline(Line),则输出的行数取决于 Line 的数值。
重载(Overload)
子程序重载
实际上通过先前的一些例子,细心的朋友可能发现,过程 Put 能处理不能类型的参数,不像 C 下的 printf 要选择输出类型,这就涉及到子程序重载:只要参数不一样,子程序可以有相同的名称。如在程序包Ada.Text_IO里的两个过程:
procedure Put (Item : in Character);
procedure Put (Item : in String);
编译器会自动选择合适的子程序,如果Put后面的参数为 Character类型,则调用procedure Put (Item : in Character);为 String 类型,则调用procedure Put (Item : in String)。这样在用户层上使用子程序简便了许多,很多常见的子程序:Get,Put_Line,Line, Page都是这样实现的----虽然在预定义程序包内针对不同参数都有一个子程序与之相对应,用户却只要记住一个名称就可以了。
运算符重载
运算符重载应该说时时刻刻都在----不同的数据类型都拥有相同的运算符:+,-,*,/等。它的原理和子程序重载是一样的,在 Ada 里,运算符也是通过子程序形式来实现。下面就给出一个“+”和 put 重载的例子:
000 -- filename: overload.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure overload is
004 type Vector is array (1 .. 5 ) of Integer;
005 a, b, c :Vector;
006 function "+"(left,right:Vector) return Vector is
007 result : Vector ;
008 begin
009 for i in left'range loop
010 result(i) := left(i) + right(i);
011 end loop;
012 return result;
013 end "+";
014 procedure Put (Item : Vector) is
015 begin
016 for i in Item'range loop
017 Put (Item(i));
018 end loop;
019 end Put;
020 begin
021 a := (1,2,3,4,5);
022 b := (1,2,3,4,5);
023 c := a + b;
024 Put (c);
025 end overload;
上例为了简化问题,有些实际中应该有的代码去除了----如检测所操作数的类型。但其它类型的运算符和重载子程序实现原理也和上例一样。
分离子程序(Separating Subprogram)
Ada 还允许子程序分成多个部份,而不是像以前的例子一样都塞在同一文件里,如将上例分成两个文件:
第一个文件:
000 -- filename: overload.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure overload is
004 type Vector is array (1 .. 5 ) of Integer;
005 a, b, c :Vector;
006 function "+"(left,right:Vector) return Vector is
007 result : Vector ;
008 begin
009 for i in left'range loop
010 result(i) := left(i) + right(i);
011 end loop;
012 return result;
013 end "+";
014 procedure Put (Item : Vector) is separate;
015 begin
016 a := (1,2,3,4,5);
017 b := (1,2,3,4,5);
018 c := a + b;
019 Put (c);
020 end overload;
第二个文件:
000 --filename:overload-put.adb
001 separate (overload) -- *注意结尾没有分号;
002 procedure Put (Item : Vector) is
003 begin
004 for i in Item'range loop
005 Put (Item(i));
006 end loop;
007 end Put;
这个程序和先前那个完全一样,只是"分了家"而已。这样分离程序有时能更好的分解程序的任务,使程序结构更为清楚。注意一下overload.adb的[014] 和 overload-put.adb的 [001],这两句就是分离子程序的主要语句。
子程序的内嵌扩展(Inline Expansion of Subprograms)
子程序可以在调用地点被内嵌扩展,以提高程序效率,它的格式为:
pragma Inline(name);
如果 name 是一个可调用的实体,子程序或类属子程序(见第11章),那么 pragma Inline 指示在所有调用该实体的地方要求对该实体进行内嵌扩展。这在封装其它语言的接口时,使用的比较多,以提高效率。