日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Object Pascal 過程與函數

 佚名2016 2016-07-27
過程與函數

過程與函數是實現一定功能的語句塊,是程序中的特定功能單元??梢栽诔绦虻钠渌胤奖徽{用,也可以進行遞歸調用。過程與函數的區(qū)別在于過程沒有返回值,而函數有返回值。


1.過程與函數的定義

過程與函數的定義包括過程原型或函數原型、過程體或函數體的定義。過程定義的形式如下:

procedure ProcedureName(ParameterList); directives;
var
    LocalDeclarations;
begin
    statements
end;

ProcedureName 是過程名,是有效的標識符。ParameterList 為過程的參數列表,需要指明參數的個數和數據類型。Directives 是一些關于函數的指令字, 如果設置多個, 應該用分號隔開。LocalDeclarations 中定義了該函數中需要使用的一些臨時變量,通常也稱作本地變量。在Begin 與End 之間是過程調用時實現特定功能的一系列語句。ParameterList、Directives、LocalDeclarations 和Statements 都是可選部分。

函數的定義與過程非常類似,只是使用的保留字不同,而且多了一個返回值類型。具體形式如下:

function FunctionName(ParameterList): ReturnType; directives;
var
    LocalDeclarations;
begin
    statements
end;

 

可以將函數需要返回的數值賦值給變量Result。如果函數體中存在著一些由于判斷而產生的分支語句時,就要在每一個分支中設置返回值。通常要根據函數的返回值來確定下一步的操作。注意,這里與Visual C 和Visual C++不一樣,把一個值賦給Result,函數并不會結束。


2.參數

函數定義時參數列表中的參數稱為形參,函數調用時參數列表中的參數稱為實參。在定義的函數原型中,多個參數之間用分號隔開,同一類型的參數可以放在一起,以逗號隔開。函數調用的時候,在函數原型中,多個參數之間用逗號隔開。
一般來說,形參列表和實參列表完全匹配是指參數的個數一樣,而且順序排列的數據類型也完全一致。對于普通的函數,如果編譯器發(fā)現實參的數據類型與形參的數據類型不匹配,會將實參的數據類型進行一次或多次的“提升”,比如把Integer 類型轉換為Double 類型??梢詾檫^程和函數的參數指定默認數值。指定默認數值的參數要放在參數列表的后部,而沒有指定默認數值的參數要放在參數列表的前部。在函數調用的時候,可以為設置了默認值的參數指定一個新值。在函數體中,各語句使用的是指定的新值,如果沒有指定新值,則使用默認值。同樣,如果存在多個設置了默認值的參數,只有在前面的參數指定了新值后,后面的參數才可以指定新值。

下面的例子定義了一個OutputNum 函數,可以將一個浮點數按指定的精度輸出。通過這個例子,讀者可以體會函數中參數的使用: 

復制代碼
program Project1;
{$APPTYPE CONSOLE}

uses Sysutils; //為了使用函數Format

function OutputNum(number:double;n:integer = 5):Boolean;
var
    Str : string; //浮點數顯示輸出的內容

begin
    if n <= -1 then //小數點后的位數要大于或等于0
        begin
            Result:=False;
            Exit; //退出顯示函數
        end
    else
        begin
            // 設置顯示的格式
            Str := Format('%*.*f', [10, n, number]);
            Result := True ;
            Writeln(Str); //顯示數據
        end;
end;

begin
    OutputNum(12.345); //n 默認為5
    OutputNum(123,3); //參數對數據類型進行升級
    //下面一句代碼不正確,故屏蔽掉
    //OutputNum(123.456789,9.13); //參數對數據類型不能降級
    //可以根據函數的返回值確定下一步的操作
    if OutputNum(123.456789,-3) = False then
        Writeln('輸出失敗。') ;
    Readln;
end.
復制代碼

運行結果如下:

12.34500
123.000
輸出失敗。

 

這里有幾點需要說明:

  • 為了使用函數Format,需要在Uses 語句中將Sysutils 單元包含進去。
  • 由于小數點后的位數不可以設置為負數,所以當出現負數時,OutputNum 函數返回False,并調用Exit 函數立刻退出OutputNum 函數。
  • 在語句OutputNum(123,3)中,首先將整型常數123 轉換為浮點型常數,然后進行參數傳遞。

最常用的參數有3 種,分別為數值參數、變量參數常量參數。
數值參數在運行過程中只改變其形參的值,不改變其實參的值,即參數的值不能傳遞到過程的外面。試看下面的例程:

procedure Calculate(CalNo:Integer);
begin
    CalNo := CalNo*10;
end;

用以下例程調用Calculate 函數:

Calculate(Number);

Number 進入Calculate 函數后,會把Number 實參拷貝給形參CalNo,在此過程中CalNo 增大10倍,但并未傳遞出來,所以說Number 值并未改變。形參和實參占用不同的內存地址,在過程或函數被調用時,將實參的值復制到形參占用的內存中。因此,在跳出過程或函數后,形參和實參的數值是不同的,但實參的值并不發(fā)生變化。

如果想改變傳入的參數值,就需要使用變量參數,即在被調用程序的參數表中的形參前加上保留字Var。例如:

procedure Calculate(var CalNo : Integer);

則CalNo 并不在內存中占據一個位置,而是指向實參Number。當一個實參被傳遞時,任何對形參所作的改變都會反映到實參中,這是因為兩個參數指向同一個地址。將上一個例程中的形參CalNo前面加上Var,再以同樣的程序調用它,則在第2 個編輯框中會顯示計算的結果,把第1 個編輯框中的數值放大10 倍。這時形參CalNo 和實參Number 的值都是Nnmber 初始值的10 倍。

如果過程或函數執(zhí)行時要求不改變形參的值,最有保證的辦法是使用常量參數。在參數表的參數名稱前加上保留字Const 就可以使一個形參成為常量參數。使用常量參數代替數值參數可以保護用戶的參數,使用戶在不想改變參數值時不會意外地將新的值賦給這個參數。下面的例子可以幫助讀者加深理解:

復制代碼
program Project1;
{$APPTYPE CONSOLE}

type
    PInteger = ^Integer; //定義指針類型

procedure P1(var N:Integer); //引用參數傳遞
begin
    N:=N+1 ;
end;

procedure P2(N:Integer); //普通參數傳遞
begin
    N:=N+2;
end;

procedure P3(PT:PInteger); //傳遞指針參數
begin
    PT^:=PT^+3;
end;

var
    i:Integer;
begin
    i:=1;
    P1(i); //將i 的值增加1
    Writeln('i:',i);
    P2(i); //希望將i 加2,但沒有實現
    Writeln('i:',i);
    P3(@i); //將i 加3    
    Writeln('i:',i);
    Readln;
end.
復制代碼

 

 

運行結果如下:

i:2
i:2
i:5

這里有幾點需要說明:

  • 一開始變量i 的數值為1,經過P1 過程的處理,將i 加1,所以顯示的第1 個i 的數值為2,這時使用的是引用參數傳遞。
  • 在過程P2 中,將形參的數值增加了2,實際上i 并沒有增加,所以顯示的第2 個i 的數值仍然為2。在這種情況下,正常的做法可以使用函數的返回值,例如:
Result:=N+2;

在調用函數的時候使用:

i:=P2(i);
  • 在過程P3 中,傳遞的是變量I 的指針,所以操作是針對i 進行的,第3 次顯示i 的數值是5。


3.過程與函數的調用約定
  在調用過程或函數的時候,如果參數列表中具有多個參數,那么參數傳遞給過程或函數的順序會對結果產生一定的影響。對于不同的語言,參數傳遞的順序是不同的:Pascal 語言是按照從左向右的順序進行傳遞的,而C 語言是按照從右向左的順序來傳遞的。

  為了確定傳遞的順序,可以在過程或函數定義的時候,在Directives 部分利用指令字指定傳遞的順序。來自Delphi 的聯機幫助的數據,如表1-13 所示,其中列舉了Directives 部分可使用的關于函數調用約定的指令字。
表1-13 定義過程與函數時對調用約定起作用的指令字

Directive 指令 Register Pascal Stdcall safecall Cdecl
參數傳遞順序 從左向右 從左向右 從右向左 從右向左 從右向左


可以通過下面的例子查看參數傳遞的順序:

復制代碼
program Project1;
{$APPTYPE CONSOLE}

function P1:Integer; //該函數將作為GetMax 函數的第1 個參數
begin
    Writeln('P1');
    Result:=0;
end;

function P2:Integer; //該函數將作為GetMax 函數的第2 個參數
begin
    Writeln('P2 ') ;
    Result:=1;
end;

//參數的傳遞方式采用pascal 方式
function GetMax(N1:Integer; N2:Integer):Integer;pascal;
begin
    Result:=N1+N2;
end;

begin
    GetMax(P1,P2);
end.
復制代碼

運行結果如下:


1 P1

2 P2

如果將GetMax 函數定義處的Directives 部分由Pascal 改為Stdcall,則運行結果變?yōu)椋?/p>

P2
P1

用戶可以修改GetMax 函數定義處的Directives 部分為表1-13 中的其他數值,測試結果是否一致。

 

4.過程和函數的重載

可以在同一個作用范圍內給不同的過程或函數取同一個名稱,這種現象就叫做重載。這樣可以使編程更方便。在重載的情況下,決定使用哪個過程或函數的依據是形參和實參的一致性,即參數個數、參數類型以及它們之間的順序,不存在一個函數調用滿足兩個重載函數的情況。另外重載函數必須用指令字Overload 來進行說明,函數的返回值類型不同就不可以作為重載函數的依據。

下面的兩個函數就是重載函數:

function Average(a:Integer; b:Integer):Double;overload; //求整形數據的平均值
function Average(a:Double; b:Double):Double;overload; //求實數數據的平均值

下面兩條語句就調用了不同的函數:

Average(3.7,4.6); //調用的是第2 個重載函數
Average(3,4); //調用的是第1 個重載函數

 

如果又定義了一個重載函數如下:

function Average(a,b:Double;c:Double=0.0):Double;overload; //求3 個實數平均值

 

從上例可以看出,盡管參數的個數與上面的兩個不同,但第3 個參數設置了一個默認值,所以當參數調用為語句Average(1.1,2.2);時,編譯系統就不知道應該使用哪個重載函數了,因為第2 個重載函數和第3 個重載函數都可以滿足要求,這樣就會出現一個編譯錯誤。


5.函數的遞歸調用

在Object Pascal 中,過程或函數必須先說明再調用。以上規(guī)則在遞歸調用時屬于例外情況。所謂遞歸調用,是指函數A 調用函數B,而函數B 又調用函數A 的情況,或是指一個函數調用自身的特殊情況。在遞歸調用中,函數要進行前置,即在函數或過程的標題部分最后加上保留字Forward。下文的例子是一個遞歸調用的典型例子:

復制代碼
program Project1;
{$APPTYPE CONSOLE}

var
    Alpha:Integer;

procedure Test2(var A:Integer);forward;

//Test2 被說明為前置過程
procedure Test1(var A:Integer);
begin
    A:=A-1;
    if A>0 then
        Test2(A); //經前置說明,調用未執(zhí)行的過程Test2
        writeln(A);
end;

procedure Test2(var A:Integer); //經前置說明的Test2 的執(zhí)行部分
begin
    A:=A div 2;
        if A>0 then
            Test1(A); //在Test2 中調用已執(zhí)行的過程Test1
end;

begin
    Alpha := 15; //給Alpha 賦初值
    Test1(Alpha); //第1 次調用Test1,遞歸開始
end.
復制代碼

程序開始時給Alpha 賦初值,并實現先減1 再除2 的循環(huán)遞歸調用,直到Alpha 小于0 為止。

 

規(guī)范化命名

在系統開發(fā)的過程中,常常要為變量、類、對象、函數和文件等命名。一般在開發(fā)需求或設計階段就必須制定出一套完整、實用的命名規(guī)則。這樣,在很大程度上可以提高系統開發(fā)的效率,便于不同模塊之間的接口,方便系統的維護。
在制定命名規(guī)則的時候,一個基本的原則就是便于使用、便于維護、風格統一。另外還應注意下面幾點:

  • 命名時要采用英文單詞,而不要使用中文拼音,尤其不要使用中文拼音第1 個字母的組合。在使用英文單詞命名時,盡量采用統一、簡單、貼切的詞語,盡可能使用完整的單詞或音節(jié)。
  • 有些名稱可以采用幾個英文單詞的組合。在組合過程中,盡量不要使用下劃線來分隔單詞,最好采用大小寫混寫的方式來實現。
  • 對于保留字和指令字可以統一全部小寫,而對于一些常量名可以全部大寫。
  • 有些名稱可以是“動詞+對象”組合而成,也可以是“對象+動詞”組合而成。一般來說,“動詞+對象”比較符合平常的語法習慣。無論采用哪種方法,整體上都應該統一。
  • 在有些情況下,要考慮到與Delphi 集成開發(fā)環(huán)境的統一。例如在Delphi 集成開發(fā)環(huán)境中,普通類的名稱一般以T 開頭,異常類的名稱一般以E 開頭。
  • 在對菜單命令的標識號命名的時候,應將所屬菜單項的名稱包含進去。比如對于“文件”菜單項中的菜單命令,可以將標識號命名為FileOpen、FileClose 等。
  • 對于一些表示集合意義的名稱,可以使用名詞的復數形式。比如窗口的集合,可以使用Windows,而不要使用WindowCollection。

 

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯系方式、誘導購買等信息,謹防詐騙。如發(fā)現有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多