過程抽象 函式(C )

2021-04-30 09:31:54 字數 4573 閱讀 9978

[程式語言用c++語言程式設計陳家駿]

一、過程抽象---函式

1.程式中呼叫的所有函式都要有定義,如果函式定義在其他檔案(如c++標準庫),或定義與本原始檔使用點之後,在呼叫之前需對被調函式進行宣告,可採用函式原型宣告表示:

《返回值型別》 《函式名》(《形式參數列》);

也可採用c語言形式函式宣告:

extern 《返回值型別》 《函式名》(《形式參數列》);

二、變數的區域性性

1.c++中,根據變數的定義位置,把變數分為全域性變數和區域性變數

2.c++把變數生存期分為:

靜態生存期變數:其記憶體空間從程式開始執行時就進行分配,直到程式結束才收回,全域性變數具有靜態生存期

自動生存期變數:其記憶體空間在程式執行到定義它們的復合語句時才分配,定義它們的復合語句結束時,空間被收回,區域性變數和函式引數一般具有自動生存期

動態生存期變數:記憶體空間用new操作分配,用delete操作收回,動態變數具有動態生存期

定義區域性變數時,可以加上儲存型別修飾符auto,static或register來指出生存期。區域性變數預設是auto。

定義為auto儲存類的區域性變數具有自動生存期。

定義為static儲存類的區域性變數具有靜態生存期。其作用是能在函式呼叫獲得上一次呼叫結束時該區域性變數的值,即static儲存類使得某些區域性變數的值能在函式呼叫多次之間得以保留,如果在乙個static儲存類的區域性變數中給出了初始化,則該初始化只在函式第一次呼叫時進行,以後呼叫中不再進行初始化,它的值是上一次函式結束時儲存的值,這種變數能受函式封裝保護。對應static儲存類的區域性變數,其作用域為定義它的函式,生存期為整個程式執行期間,在包含static儲存類區域性變數的函式被呼叫前,該變數雖然存在,但不可訪問。

定義為register儲存類的區域性變數也具有自動生存期,並建議編譯器把相應的區域性變數空間分配在cpu的暫存器中,提高對區域性變數的訪問效率,只是建議,也有可能分配在記憶體中,視cpu暫存器使用情況而定

當乙個程式執行時,作業系統將為其分配一塊記憶體空間,包括四個部分:

靜態資料區:用於全域性變數、static儲存類的區域性變數以及常量的記憶體分配

**區:用於存放程式的指令,對應c++,**區存放的是所有函式**

棧區:用於儲存auto儲存類的區域性變數、函式的形參及函式呼叫時有關資訊(函式返回位址等)的記憶體分配

堆區:用於動態變數的記憶體分配

靜態資料區和**區的大小事固定的,而棧區和堆區大小不斷變化,os對其最大值有一定限制。在c++中,如果定義乙個變數時沒有對其初始化,對於全域性變數和static儲存類的區域性變數,編譯程式將隱式地自動把它們按位模式初始化為0;對應其它變數,編譯程式不會對它們進行初始化。對變數進行顯示初始化是一種良好的習慣。

3.為了便於管理、組織、理解c++程式,通常對構成c++程式的各個邏輯單位(全域性函式、全域性常量、全域性變數/物件、類等)的定義進行分組,分別把它們放在若干原始檔中,以避免對程式一點修改導致對整個程式的重新編譯和便於多人合作開發乙個程式。分組即模組化,基本原則是:模組內部內聚性最大、模組之間耦合度最小。模組是乙個可單獨編譯的程式單位,一般包含兩個部分:介面和實現;c++中介面一般於.h檔案中存放;實現於.cpp檔案中存放。

4.#include 《檔名》:在系統指定的目錄下尋找指定檔案

#include "檔名":現在包含#include命令的原始檔所在目錄下查詢指定檔案,然後再在系統指定目錄下查詢。

5.c++把標示符作用域分成:

區域性作用域:在函式定義或復合語句中,從標示符定義點開始到函式定義或復合語句結束之間的程式段。區域性常量名、區域性變數名/物件以及函式的形參名具有區域性作用域,靜態作用域機制:外層標示符作用域應該是從其潛在的作用域中扣除內層同名標示符作用域所得到的作用域,如:

void f()

…x…;//外層x

}全域性作用域:構成c++程式的所有原始檔。

檔案作用域:指單獨的原始檔,在全域性標示符的定義中加上static修飾符,該全域性標示符就成了具有檔案作用域的標示符,只能在定義它們的原始檔中使用。在函式外用const定義的常量名具有檔案作用域。

函式作用域:指整個函式定義所構成的程式段。語句標號是唯一具有函式作用域的標示符,可以在定義它們的函式體中任何地方訪問它們。函式作用域與區域性作用域區別是:a.函式作用域為整個函式,而區域性作用域只是從定義點開始到函式定義或復合語句結束;b.函式體中,語句標號只能定義一次,即使是內層的復合語句中,也不能與外層相同的語句標號;c.c++把語句標號作為特殊的標示符看待,與其他類的標示符屬於不同的範疇,語句標號的作用域可以撤同名的其他標示符作用域重疊,如:

void f(int x)

函式原型作用域:指用於函式宣告的函式原型,其中形參名的作用域從函式原型開始到函式原型結束

類作用域:

名空間作用域:對於不是定義在某個名空間中的全域性程式實體,可以把它們看成是定義在乙個全域性的無名空間中,可以把檔案作用域的程式實體定義為乙個區域性與各個原始檔的無名空間。

//file.h

namespace a

//file.cpp

namespace a

void g()

}#include "file1.h"

int main()

或int main()

或int main()

三、帶預設值的形式引數

a.有預設值的形參應處於形參表的右部

b.對引數預設值指定只在函式宣告處有意義,在函式定義時指定預設值沒有意義,除非宣告定義同時進行

c.在不同原始檔中,對同乙個函式的宣告可以對它的同乙個引數指定不同的預設值,在同乙個原始檔中,對同乙個函式的宣告只能對它的每乙個引數指定一次預設值

四、內聯函式和巨集:解決函式執行帶來的執行效率降低的問題

1.巨集定義(4種):

#define 《巨集名》 《文字串》:字串及注釋中的相應值不會被替換,如#define pi 3.14;

#define 《巨集名》(《參數列》) 《文字串》:出現《巨集名》的地方用文字串代替,《文字串》中引數(相當於形參)將被替換成《巨集名》提供的引數(相當於實參),如果一行寫不下,可在本行最後用續行符"/"後跟乙個回車轉到下一行。如:

#define max(a,b) (((a)>(b))?(a):(b))//該行有無分號有時會影響結果正確性

int main()

#define 《巨集名》:告知編譯程式《巨集名》已被定義,不做文字替換,實現條件編譯

#undef 《巨集名》:取消某個巨集明定義,其後的《巨集名》不再進行替換和不再有意義

2.巨集定義缺陷:

a.有時會重複計算,如:max(x+1,y+2);則被編譯程式替換為:(((x+1)>(y+2))?(x+1):(y+2))

b.不進行型別檢查和轉換

c.在c++編譯結果中,所有巨集定義已不存在,會給一些軟體工具(如除錯程式)在源程式和目標程式之間進行交叉定位帶來困難

3.內聯函式:在函式返回型別之前加上inline,建議編譯程式把該函式的函式體展開到呼叫點,形式上屬於函式,效果上具有巨集定義的高效,只是建議,視函式體的具體實現而定,有些函式即使加上inline,編譯程式也不把它作為內聯函式,如遞迴函式一般不能作為內聯函式。內聯函式具有檔案作用域,在呼叫內聯函式時一定要見到內聯函式的定義,僅僅對其宣告是不行的。常把內聯函式定義放在標頭檔案中,其他原始檔需要時用#include包含進來即可

五、條件編譯作用

a.由編譯程式根據不同的環境對程式中相應的與環境有關的**進行編譯,避免**重複,與環境無關的**只寫一次。

b.不會重複包含某個.h檔案,如在該.h檔案頭加入

#ifndef modual1

#define modual1

……#endif

則編譯程式只對第一次包含的內容進行編譯。

c.編譯程式除錯,實際上斷言可以達到類似效果,c++標準庫提供了巨集assert來表示斷言,在標頭檔案(cassert或assert.h中定義),該巨集要求乙個型別為int的表示式作為其引數,如果表示式值為0,會顯示相應的表示式、斷言所在源檔名及斷言所在的行號等診斷資訊,然後呼叫abort終止程式執行;當表示式不為0時,程式繼續執行

條件編譯命令的格式1:

#ifdef 《巨集名》 / ifndef 《巨集名》

《程式段1>

[#else

《程式段2>

#endif

條件編譯命令的格式2:

#if 《常量表示式1> / #ifdef 《巨集名》 / #ifndef 《巨集名》

《程式段1>

#elif 《常量表示式2>

《程式段2>

[#else

《程式段n+1>]

#endif

其中常量表示式為整形常量表示式,其運算元只能是符號常量、字面常量或"define(《巨集名》)",對應define(《巨集名》),當巨集名有定義時,其值為1,否則為0

六、標準庫

c語言標準庫主要包含了一些常用的函式定義和巨集定義,它們的頭檔名種通常包含".h",c++標準庫也提供相應的標頭檔案,把c標準庫檔名的".h"去掉,在檔名前加上c,很多c++實現為了保證與c相容,通常提供2套頭檔案。c++標準庫的程式實體是在名空間std中定義的,在c++程式中使用c標準庫功能時,如果包含的是相應的c++標頭檔案,應該通過名空間std來使用這些功能。

C 抽象類和抽象函式

所謂抽象就是沒有具體只有其意。在繼承中,如果想要定義一群派生類共有的共性卻沒有具體實現的 方法 時,可以用抽象類實現了。例如語文老師 數學老師 英語老師等都是老師,老師都有教學的任務。所以教學就是共性。因為教學不確定教學的內容和時間。所以教學的內容 時間都不同都需要針對不同的的派生類來定義。抽象類和...

C 繼承 多型 虛函式 抽象

一 繼承 1 如果你以乙個 基類指標 指向 派生類物件 那麼經由該指標你只能呼叫基類所定義的函式 2 如果你以乙個 派生類指標 指向乙個 基類指標 你必須先做明顯的轉型操作。3 如果基類和派生類都定義了相同名稱的成員函式,那麼通過物件指標呼叫成員函式是,到底呼叫到那乙個函式,必須視該指標的原始型別而...

c 函式執行過程(函式棧)

本節我們重點討論棧指標esp和幀指標ebp,圍繞這兩個重要的暫存器,推導出函式棧幀結構。閱讀本文之前補充乙個概念 棧幀 每個函式的棧稱為一幀,也就是該函式的棧幀。函式棧的基位址 ebp 稱為棧幀指標,訪問函式中的引數或區域性變數,都是通過ebp加上偏移量來獲得。一 壓棧和出棧的操作本質 上一節我們了...