日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++的程序的文件结构

發布時間:2023/12/20 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++的程序的文件结构 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉載:http://www.cnblogs.com/Charles2008/archive/2009/09/03/1559935.html的博客
因項目需要,需要對C++的程序的文件結構有所掌握:因此在網上找了下面的文章供學習和參考。希望對剛入門的C++朋友能提供一些幫助。
轉載:http://www.d2school.com/

程序是由什么組成的? 學習到今天,我們至少有兩個答案:

第1,程序由代碼語句組成。正是一行行的代碼,組成了一個完整的程序。

第2,程序由函數組成。一個個函數之間的互相調用,最終構建出一個完整的程序。

今天我們又有一個新的回答:“程序由文件組成”。

程序為什么需要使用多個文件?

一個小的程序,可以只寫一個源文件,但程序稍微一大,就需要將其中不同的邏輯實現放到不同的源文件.對于需要多人一起開發的軟件,自然更需要多個源文件。

?

14.1 源文件和頭文件

 

和別的一些語言不同,C,C++的代碼文件有“頭文件”和“代碼文件”之分。二者合起來我們稱為單元(Unit)文件。

 

擴展名為 .c 或 .cpp 的文件,主要用以實現程序的各種功能,我們稱為代碼文件。

擴展名為 .h 的文件,稱為頭文件。在頭文件里主要寫一些函數、數據(包括數據類型的定義)、等的聲明,這樣可以在多個.c或.cpp文件內共享這些函數、數據。第12章我們提過到頭文件的功能。說它可以起到函數“名片夾”的作用。 

大都數時候,源文件和頭文件是對應出現的,比如有一個 A.cpp 的源文件,就會有一個 A.h 的頭文件。這種情況在我們寫應用程序時,更是常見。所以C++ Builder對此進行了強化。比如,它支持在同名源文件和頭文件之間通過熱鍵來回切換。在CB6.0里,編輯器打開對應的源文件和頭文件時,將顯示為同一頁下的兩個子頁。

我們來實際動手看看源文件與頭文件在CB里的對應關系。 

運行 C++ Builder 6或5。

這一次我們需要一個空白的Windows工程。很有可能,在你打開CB時,它就自動為你打開了一個工程。為了不出錯,我們還是親自建一個。CB6請使用主菜單:File | New | Application;而CB5則使用:File | New Application 新建一個Windows 空白工程 如果在這過程中CB出現是否存盤的詢問,請回答不存盤。 

找到“代碼窗口”。如果你看到的是一個叫"Form1"的表單,請按F12,“代碼窗口”將跑到前面。它的標題應該是默認的"Unit1.cpp"。正是當前代碼文件的文件名。如下圖: 

對于CB6,還可以看到在該窗口的底部有這樣一個分頁: 

 

源文件:Unit1.cpp 和頭文件:Unit1.h 并列著,我們可以方便地選擇。至于 "Diagram",稱為“圖解”。這是一個給這個源文件加配套注解,及表單上各控件的依賴關系的地方。如果是一個開發小組在進行共同開發,嚴格地要求每個成員為每個單元文件寫上“Diagram”,可以更好地實現程序員之間的溝通。

CB5沒有這些,不過下面的熱鍵操作兩個版本均一樣的,要求大家記住。

Ctrl + F6 可以在源文件和頭文件之間來回切換。請大家試試。這個簡單的操作將在我們今后的編程過程中高頻率地使用。

?

14.2 如何創建多個單元文件

 

前面我們在“Windows應用程序工程”中看到了頭文件與源文件的匹配關系,在“控制臺”的工程中,也同樣存在。不過由于控制臺經常只用來寫一些小小的程序,所以往往只需一個源文件即可。由于只有一個源文件,所以也就不存在函數、數據在多個文件之間“共享”的需要,因此邊頭文件也就可以不提供。

 

那么,是不是只有在程序很大,或者只有在有很多人同時開發一個軟件時,才需要多個源文件呢?

這就好像你家里只有兩本書:《紅樓夢》和《格林童話》,是把它們放在同一個抽屜里呢?還是分開放到兩個抽屜里?我覺得后者是比較好的選擇。因為我們常常希望家里看《格林童話》的人,最好不要去看《紅樓夢》。

程序也一樣,最好把不同的邏輯實現,放到不同的源文件中。

 

下面我們做一個實例。例子的代碼我們都已經學過。目標是實現一個可以求統計值和平均值的程序。

根據我們現在所學的情況,我把這個工程中的代碼分為三個源代碼:

其一:主程序。就是main()函數所在的代碼。這個源文件實現總的流程。我將該文件取為 main.cpp

其二:計算總和及計算平均值的代碼。這個源文件負責用戶計算過程,也包括每個過程所需輸入輸出。該文件將被存盤為mainfunc.cpp 意為主要功能。

其三: assifunc.cpp。表示輔助功能函數所在代碼。它只提供一個函數:將用戶輸入的大寫或小寫的字母'Y''N' 確保轉換為大寫。這個函數將main()主函數內,判斷用戶是否繼續時用到。

 

新CB新建一個控制臺程序(如果你還開著上個程序,先選File | Close All關閉它)。CB會自動生成第一個文件,不過現在的名字為“Unit1.cpp"

接下來是一項新工作,我們來添加兩人新的單元文件,即上面說的“其二”和“其三”。

CB6 :File | New | Unit;CB5:File | New Unit

請進行兩次以上操作,CB將為我們生成新的兩個單元文件:Unit2.cppUnit3.cpp。大家可以再試試 Ctrl + F6(注意,第一個單元文件:Unit1.cpp 沒有配套的.h文件,所以不要在該文件里嘗試Ctrl + F6)

然后選擇File | Save All。全部存盤,最好不要存在CB默認的目錄下。記得按以下關系重命名:

Unit1.cpp 存盤為 main.cpp

Unit2.cpp 存盤為 mainfunc.cpp

Unit3.cpp 存盤為 assifunc.cpp

至于總的工程,隨你便,我圖方便,還是叫:Project1.bpr

 

(現在我們第一次在一個工程中用到多個源文件。所以你得學會如何快速打開一個工程中某個源文件——當然,現在這三個文件都已經打開著,不過假設你有點事關閉CB,我們不希望下回打開這個工程時,你“找”不到第2和第3個文件了——請點擊CB工具欄上的這個圖標:,將出現源文件列表對話框,如左圖)

 

 

接下來講在這三個文件中,我們分別寫些什么?大多數代碼我們都已經在前面學過,所以我對代碼的功能不作太多的解釋。我們的重點是:三個源文件之間的代碼如何實現“溝通”。

 

第一個文件:main.cpp 用來實現程序的主流程。

在 main.cpp 中的main()函數內,我們加入代碼。

 

#include <iostream.h>

... ...

int main(int argc, char* argv[])

{

?? char ch;

?? int count; //求總和或平均值時,需要輸入的成績個數

 

?? do

?? {

????? cout << "1)求總和" << endl;

????? cout << "2)求平均" << endl;

????

????? cout << "請選擇(1 或 2)";

????? cin >> ch;

?????

????? //輸入有誤,重輸:

????? if(ch != '1' && ch != '2')

????? {

???????? cout << "輸入有誤,請重新輸入!" << endl;

???????? continue;

????? }

?????

????? cout << "請輸入個數:";

????? cin >> count;

?????

????? //根據用戶的選擇,調用不同函數:

????? switch(ch)

????? {

???????? case '1' :

??????????? CalcTotal(count); //需要調用的函數之一

??????????? break;

???????? case '2' :

??????????? CalcAverage(count); //需要調用的函數之一

??????????? break;

????? }

????????

????? //是否繼續:

????? cout << "是否繼續?(y/n)";

????? cin >> ch;

?????

????? //確保轉換為大寫:

????? ch = ToUpper(ch); //需要調用的函數之一

?? }

?? while(ch == 'Y');

??

?? return 0;

}

 

代碼中,紅色部分的注釋表明,主函數main()需要調用到三個自定義函數。但現在我們一個也沒有定義。和往常把所有的函數定義在同一個代碼文件中不同,今天我們需要把它們分開到不同的代碼文件。

 

第二個文件:mainfunc.cpp 存放和計算有關的兩個過程(函數)。

先看:CalcTotal()和CalcAverage()。這兩個函數我們將在mainfunc.cpp文件內定義。你可能又忘了“定義”這個術語?呵,就是“實現”,更白點,就是在mainfunc.cpp文件內“寫”這兩個函數。

 

下面是mainfunc.cpp的內容。在我們輸入以下代碼時,mainfunc.cpp已經有了一些必要的內容,下面的代碼,除了“#include ..”一行在文件最首外,其它均在原有內容之后添加。

 

#include <iostream.h> //在文件最首行

... ...

//---------------------------------------------------------------------------

//求總和的過程

//參數:n 用戶需要輸入的個數

void CalcTotal(int n)

{

?? int num;

?? int sum = 0;

??

?? for(int i=0;i<n;i++)

?? {

????? cout << "請輸入第" << i+1 <<"個整數:";

????? cin >> num;

?????

????? sum += num;

?? }

??

?? cout << "總和為:" << sum << endl;

}

//---------------------------------------------------------------------------

//求平均值的過程

//參數:n 用戶需要輸入的個數

void CalcAverage(int n)

{

?? int num;

?? int sum = 0;

?? float ave;

?? for(int i=0;i<n;i++)

?? {

????? cout << "請輸入第" << i+1 <<"個整數:";

????? cin >> num;

??

????? sum += num;

?? }

?? //注意不要除0出錯:

?? if( n >=0 )

?? {

????? ave = (float)sum / n;

????? cout << "平均值:" << ave << endl;

?? }

?? else

?? {

????? cout << "個數為0,不能求平均。" << endl;

?? }

}

//---------------------------------------------------------------------------

 

第三個文件:assifunc.cpp 用以存放輔助作用的函數,現在只有一個。

現在還差一個函數:ToUpper()。這個函數用來將用戶輸入的某個小寫字母轉換為大寫。當然,如果用戶輸入的不是小寫字母,那就不用轉換。和上面的兩個函數不同,它需要返回值。

我們把ToUpper()函數單獨放在assifunc.cpp里。同樣,下面的代碼加在該文件中原有的代碼之后。不過本文件不需要include <iostream.h> ,因為沒有用到 cin,cout等。

 

//小寫字母轉換為大寫

//參數: c 待轉換的字符

//返回值: 轉換后的字符,如果原字符不是小寫字母,則為原字符

char ToUpper(char c)

{

?? int ca = 'A' - 'a'; //大寫字母和小寫字母之間差距多少?

?? if(c >= 'a' && c <= 'z')

????? c += ca;
 

?? return c;

}

 

至此,所有自定義函數都已完成定義(實現),而三個文件的主要內容也以確定。讓我們看看示意圖:

 

 

main.cpp中的main()函數調用了三個函數。回憶我們學習過的“如何調用函數”的知識,當前代碼在調用一個函數時,必須能“看到”這個函數。盡管CalcTotal()、CalcAverage()、ToUpper()三個函數所在文件都在同一工程里,但是在main.cpp里的代碼,還是看不到它們。想一想我們以前說的“請修理工”的比喻。現在情況是:在你所住的小區,甚至就是同一樓道里,就有一個電視修理工,但可惜你們互不認識,所以當你電視壞了,想“調用”一個修理工時,你還是找不到修理工。哎!要是有它的名片就好了。

讓我們試試看,按Ctrl + F9,編輯該工程。出錯!

正好是三個錯。分別告訴我們調用了三個沒有定義的函數(Call to undefined function ...)。

 

(如果你出現的是一堆錯,那有可能是你沒有在前兩個文件內最首行寫:

“#include <iostream.h>”

或者是你有些代碼輸入有誤。)

 

如何消除這三個錯?兩種方法。

第一種方法就是以前我們在講“如何調用函數”的時候所說的,直接在調用直接聲明要調用的函數。這里寫出代碼,算做是一次復習,然后我們將講該方法不好之處。

 

在 main.cpp 的 main()函數之前加入如下三行函數聲明:

 

void CalcTotal(int n);

void CalcAverage(int n);

char ToUpper(char c);

 

int main(int argc, char* argv[])

{

?? ... ...

}

 

(上例中,盡管你可以將三行函數聲明寫在 main()函數體內,但不建議這樣做)。

 

如果你一切輸入正確的話,現在按Ctrl + F9 或 F9將可以完成編譯或運行。

對于現在這個工程,這種方法確實也不能指責它有何不利之處。問題在于,如果我們還有其它文件中代碼需要調用到這三個函數,我們就不得不在其它文件中也一一寫上這三行聲明。所以另一種方法是:把源文件中需要對外“共享”的函數聲明統一寫到某個頭文件,然后凡是需要用到的其它文件,直接使用“#include"語句來包含該頭文件,從而獲得這些函數聲明。

?

14.3 如何寫頭文件

 

在CB中,如果你通過上小節的方法新建個單元文件,那么CB將自動同時生成源文件和頭文件。其實在CB里,源文件和頭文件合稱為單元文件,它們有相同的文件名,而擴展名一者為.cpp,另一為.h。

 

14.3.1 在頭文件內加入函數聲明

 

頭文件:mainfunc.h

CalcTotal()和CalcAverage()函數定義在 mainfunc.cpp文件里,所以它們的聲明最好寫在對應的頭文件mainfunc.h內。

下面我們就來看如何在頭文件mainfunc.h 內增加函數聲明。

一開始,頭文件內有以下這些代碼。另外,我增加了一行用于標明我們新加的代碼應寫在哪里。

//---------------------------------------------------------------------------

#ifndef mainfuncH

#define mainfuncH

//---------------------------------------------------------------------------

/* !!!頭文件中,我們新增的代碼必須寫在此處!!!? */

#endif

 

和源文件中新增代碼添加在最后不一樣,頭文件中新加代碼 必須在#endif之前插入。所以本例中,加完函數聲明的代碼應如其下所示。(另外,CB總是在頭文件的第二行留了一行空白行,我不知道它這是有意還是無意。總之這里是我們寫本文件總體注釋的好地方。記住,頭文件像名片,用于讓別人看,很有必要寫得詳細點)

//---------------------------------------------------------------------------
?? //主要操作函數

#ifndef mainfuncH

#define mainfuncH

//---------------------------------------------------------------------------

//計算總和:

void CalcTotal(int n);

//計算平均值:

void CalcAverage(int n);

//---------------------------------------------------------------------------

#endif

 

這就是“在頭文件中聲明函數”的整個過程。下面是另外一個頭文件。

 

頭文件:mainfunc.h

//---------------------------------------------------------------------------

//輔助操作函數

#ifndef assifuncH

#define assifuncH

//---------------------------------------------------------------------------

//將字符轉換成大寫

char ToUpper(char c);

#endif

 

今天我們學的是如何在頭文件內聲明函數,以后我們需要在頭文件內聲明變量,或者定義新的數據類型,它們都一樣需要在上述的#endif之前加入。

 

14.3.2 最常見的預編譯語句

 

現在來解釋這三行話:

#ifndef mainfuncH

#define mainfuncH

 

#endif

 

中間的 #define mainfuncH 我們有點臉熟。在第五章《變量與常量》中,我們講過用宏表示常數。語法為:

#define 宏名稱 宏值

 

比如,定義一個∏值:

#define PAI 3.14159

 

這里我們學的是宏定義的另一種用法:僅僅定義一個宏,不需要給出它的值,語法為:

 

#define 宏名稱

 

比如:#define mainfuncH

 

定義了一個宏:mainfuncH。如果你無法理解“宏”這個詞,不妨就當把它解釋成“記號”。即編譯器通過該語句,做了一個記號,記號名稱為:mainfucH。

這么做的作用是什么呢?我們繼續看上下文。

 

#ifndef 中, if 是“如果”,n 是 no,即“還沒有”,def是 define,即“定義”,那么:

#ifndef mainfuncH 意為:“如果還沒有定義mainfuncH這個宏”,那么……

那么之后做什么呢?就是一直到 #endif之間的語句。

 

總的再來看一遍:

 

mainfunc.h 中的主要內容:

 

#ifndef mainfuncH

#define mainfuncH

 

void CalcTotal(int n);

void CalcAverage(int n);

 

#endif

 

當編譯第一次編譯mainfunc.h文件時,宏 mainfuncH 還沒有定義,因些,編譯器通過對 #define mainfuncH的編譯而產生了宏 mainfuncH。當編譯器第二次編譯到 mainfunc.h文件時,宏mainfuncH 已經存在,所以該頭文件被直接跳過,不會重復處理該頭文件中內容,比如上面的兩個函數聲明。

你可能會問兩個問題:第一,為什么編譯器可能多次編譯到同一個頭文件?第二,為什么源文件,比如mainfunc.cpp就不需要用到#ifndef... #endif?

這兩個問題只要回答了其中一個,另一個也就自然消解。

 

這是由頭文件特性所決定的。頭文件是用來被別人包含(include)的。誰都可以指定要包含某一頭文件,這樣就可能造成對該頭文件的重復包含。

假設有頭文件head.h。如果A文件包含了head.h,而B文件也包含了head.h,那么編譯器不會在編譯A和編譯B時,都要對該頭文件嘗試編譯一次。

另外,頭文件本身也可以包含另一個頭文件,這種情況下,各文件之間互相嵌套包含的情況就更多了。

 

源文件(.c或.cpp)盡管可以,但一般不被用來被別的文件包含,所以不需要在源文件中加這些語句。當然,如果需要,你也可以源文件中使用 #ifndef...#endif。

 

每生成一個頭文件,包括在重命名它時,CB會為我們取好該頭文件中,上述的宏名稱,它取該頭文件的全小寫文件名,加上一個大寫的‘H’字母,比如: "mainfuncH"。請大家不要改變該宏的名稱,以免出錯。

 

除了 #ifndef ... #endif 語句外,還有它的相反邏輯的語句:?

#ifdef ... #endif 它是在如果有定義某個宏,那么,編譯將繼續其后的語句。

 

另外就像有if 語句,還有 if...else...語句一樣,有 #ifdef ... #endif,也就還有這個語句:

#ifdef

... ...

#else

... ...

#endif

 

不過這些都和我們這里的頭文件相關不大,我們暫時不講。最后我們來解釋一個名詞“預編譯”。

編譯器在編譯代碼時,至少需要兩遍的編譯處理,其中第一次,就是專門用于處理所有以 #開頭的語句,如上述的#ifndef...#endif、#define等等。這一遍處理,我們稱為預編譯

 

14.4 如何使用頭文件

 

事實上我們經常在使用頭文件。不過,以前我們一直在使用別人的頭文件,今天是第一次使用我們自已的寫的頭件。

以前,我們幾乎每個例子,包括今天的例子中,都需要在源文件的頂部寫上一行:

#include <iostream.h>

或者:

#include <stdio.h>

 

iostream.h和stdio.h都是CB提供給我們的頭文件。這些頭文件隨CB安裝時,被保存在固定的文件夾內

今天的例子中,main.cpp 需要使用到在 mainfunc.h 和 assifunc.h。這是我們自己寫的頭文件,它們保存在我們自定的文件夾中

包含自已寫的頭文件,和包含CB提供的頭文件并無多大區別。

請在 main.cpp 代碼頂部,加入以下黑體部分:

 

#include <iostream.h>

#include "mainfunc.h"

#include "assifunc.h"

//---------------------------------------------------------------------------

 

二者的細小區別是,包含CB提供的頭文件時,用尖括號<>;而包含我們自已的頭文件時,使用雙引號“”。CB據此判斷如何找到指定的頭文件。<>相當于告訴CB,這是你自已提供的頭文件,到你安裝時的頭文件目錄下找去吧,而“”則是告訴CB,是這我自已寫的頭文件,請首先到我當前工程所在目錄下查找,如果找不到,再到別的可能的頭文件目錄下找這個文件。(別的還有什么目錄可能存放當前工程的頭文件呢?稍后會講。)

 

現在,我們讓main.cpp包含了它想要的頭文件,頭文件內有它所需函數的正確聲明,那么main.cpp中原來的這三行就多余了:

void CalcTotal(int n);

void CalcAverage(int n);

char ToUpper(char c);

請刪除。 然后,按F9,程序正確編譯,然后運行。這里我們不關心它的運行結果。

 

現在來看一眼在CB中如何設定某一工程的頭文件目錄。

必須先說清楚,在相當長的一段時間內,我們并不需要去進行此設置。對于CB提供的頭文件,它們固定就在CB安裝時自動存儲的某些目錄下,你只要記得包含這些頭文件時,使用<>即可。對于我們自已寫的頭文件,我們都把它們和工程文件存放在同一目錄下,暫時還沒有什么理由需要把某個或某些頭文件“扔”在別的目錄下。所以,記住在包含自己的頭文件時,對使用“”即可。

首先保證當前CB正打開著上面的那個例子工程。

然后,主菜單: Project | Options 或按 Ctrl + Shift + F11,打開“工程設置(Project Options)”對話框,并切換到“目錄與條件(Directories/Conditionals)”頁:

 

圖中有關目錄的設置共六行,我們說其中常用的四行。

最主要的,當然是今天所說的“頭文件目錄”。當 CB 編譯時,當它遇到這樣一行:

 

#include "xxxx.h"

那么,它必須找到文件xxxx.h。如果,你寫的是絕對路徑:#include "c:\abc\123\xxxx.h",那自然沒有查找這一說,不過我們不會喜歡這樣寫程序,因為我們不希望源代換個位置就得一一去改那些絕對路徑。事實上我們不可能把頭文件到處放,總是固定那么幾個目錄,絕大多數就一個:所有源文件和頭文件都在當前工程所在目錄下。這里可以添加,刪除,修改一些目錄位置,CB將按本設置中的目錄次序去查找頭文件。

請點擊“頭文件目錄”右邊,帶 "..."的小按鈕。出來一個新的對話框:

($BCB) 表示Borland C++Builder 的安裝目錄。

 

在這里,你可以修改(Replace),增加(Add),刪除(Delete),調整次序(向上和向下的藍箭頭)各個頭文件目錄。CB6還提供了對無效目錄的判斷,如果列表中列出的某個目錄實際上并不存在對應的文件夾,則將以灰色顯示,并且可以用"Delete Invalid Paths"按鈕全部刪除。

 

我們什么也不用做。點 Cancel, 放棄就是。

 

其它目錄的設定,操作完全一樣。

 

關于在工程中如何使用頭文件,我們就說這些了。

 

14.5 變量在多個源文件之間的使用

前面講的是,通過在頭文件中聲明函數,可以達到讓這個函數被其它文件共用的作用。同樣地,變量也可以在多個源文件之間“共享”。下面我們就要講,如何通過聲明變量,以達到讓其它文件共用同一個變量的目的。

 

14.5.1 變量聲明

先說說“聲明變量”。好像以前的課程只教過我們:定義變量,定義函數,聲明函數,沒有講過“聲明變量”啊?

 

我們很早就學過如何定義一個變量。(5.1.2)

 

比如:

 

//定義一個整型變量:

int age;

 

//然后,在后面的某處代碼中使用這個變量:

... ...

age = 18;

cout << age << endl;

... ...

 

 

但是,我們沒有遇到過如何聲明一個變量。這是因為,定義一個變量的同時,也就聲明了一個變量;絕大多數的時候,我們都是可以需要某個變量時,直接定義它。

 

今天的情況有點不一樣。我們需要在某個源文件中定義一個變量,然后,在另外一個源文件中使用這個變量。

 

仍以前面 age 變量為例:

 

//我們在 A.cpp 文件中定義了這個變量:

int age;

 

//然后,在 B.cpp 文件中要使用這個變量:

age = 18;

cout << age << endl;

 

問題就出來了:在編譯 B.cpp 文件時,編譯器會說:“age 這個變量沒有定義啊?”——當編譯器在編譯 B.cpp時,它并不懂得去A.cpp里去找有關 age 的定義。

那么,能不能在B.cpp里再定義一次age變量呢?

 

//A.cpp文件中:

int age;

 

//B.cpp文件中:

int age;

age = 18;

cout << age << endl;

 

這樣,單獨編譯A.cpp,或B.cpp,都可以通過。但一旦要編譯整個工程,編譯器又會報錯:“怎么有兩個 age 變量的定義啊”?

不要嘲笑編譯器為什么這么笨笨。C,C++是一門嚴謹的的計算機語言,我們不能指望編譯器會“智能”地猜測程序員的企圖。

 

解決方法是,僅在一處定義變量,別的代碼需要用到該變量,但無法看到前面的定義時,則改為“聲明變量”。

 

聲明變量的語法:

extern 數據類型 變量名

 

和定義變量的語法相比,多了前面的 extern 這個關鍵字。

 

extern 意為“外來的”···它的作用在于告訴編譯器:有這個變量,它可能不存在當前的文件中,但它肯定要存在于工程中的某一個源文件中。

 

這就好像:微軟公司在北京招人,微軟的報名方法是:在北京的應聘者必須當天去面試,而外地應聘者則通過發e-mail先報名,然后以后再去面試。 在C,C++里,不處于當前源文件中的變量被稱為外部變量。比喻中,發e-mail就相當于外部變量在某一個源中寫個聲明。聲明什么呢?就是聲明“我存在啊!雖然我現在不在這里,但是我真的存在!”

 

上例中,正確的代碼應該這樣寫:

 

//A.cpp文件中:

int age;

 

//B.cpp文件中:

extern int age;

age = 18;

cout << age << endl;

 

變量 age 是在A.cpp文件里定義的,當B.cpp文件要使用它時,必須先聲明。這就是我們講半天課的核心。

 

(有些教材并不認為 extern int age; 是在聲明一個變量,它們把這也稱為是“定義變量”的一種,只不過它是定義了一個名部變量。我認為這樣認為不好,一來它造成了學習者認為“變量可以重復定義”的錯誤認為,二來它也造成了不統一,函數有“定義”和“聲明”兩種形式,而變量都沒有“聲明”。

可能你會說,現在也不統一啊?函數聲明沒有“extern",而變量卻需要?呵呵,其實恰恰相反。函數聲明本來也是需要一個“extern”的,比如:

 

extern void CalcTotal(int n);

你在代碼里這樣完全正確!只不過由于函數聲明和函數定義的格式區別很大,(聲明沒有函數體,定義則必須有函數體),所以這個extern就算不寫,也可以讓編譯器認出來它是一個“聲明”。結果就規定可以不寫"extern"了。

而變量呢?

extern int age;???? //這是聲明

int age;??????????? //這是定義

你看看,不寫"extern"可不行! 就靠它來區分是定義還是聲明了。

如此而已。)

 

14.5.2 多個文件中共享變量的實例

 

做一個最簡單的例子。新建一個控制臺工程。然后再加一個單元文件。把工程存盤為Project1.bpr,把兩個源文件分別存盤為Unit1.cpp、Unit2.cpp (即,都采用默認文件名)。

 

程序內容是:在 Unit1.cpp 內定義一個變量,即:int age,并且,要求用戶輸入。在Unit2.cpp里,寫一函數,OutputAgeText(),它根據 age 的值, 輸出一些文本。

 

請問,變量 age 在哪里定義?又在哪里聲明?

 

定義指定是在 Unit1.cpp 文件里,而聲明,則可以在 Unit2.cpp內直接聲明(如上例中的紅色代碼),也可以是在頭文件 Unit1.h 里聲明,然后在 Unit2.cpp 內使用 include 來包含 Unit1.h。 事實讓,聲明也可以放在 Unit2.h內。只要能讓Unit2.cpp“看到”這個聲明即可。這一點和函數的聲明一個道理。

 

我們采用放在Unit2.cpp中的方法,該方法所需代碼如下:

 

//Unit1.cpp 內的主要代碼:

 

#include <iostream.h>

#include <conio.h>

#pragma hdrstop

#include "Unit2.h"

... ...

//---------------------------------------------------------------------------

int age; //全局變量,年齡

#pragma argsused

int main(int argc, char* argv[])

{

?? cout << "請輸入您的年齡:" ;

?? cin >> age;

 

?? //調用Unit2.cpp中的函數,該函數根據age,作出相應輸出

?? OutAgeText();??

??

?? getch();

?? return 0;

}

//---------------------------------------------------------------------------

 

 

//Unit2.cpp 中的主要代碼:

#include <iostream.h>

... ...

extern int age;? //需要Unit1.cpp內定義的變量

 

//報名參加“沒有彎路”的學員各行業,年齡段也各處不同,在此,我們用這個函數作為共勉!

void OutAgeText()

{

?? if(age < 15)

????? cout? << "計算機要從娃娃抓起!" << endl;

?? else if(age < 25)

????? cout << "青春年華,正是學習編程的黃金時代!" << endl;

?? else if(age < 35)

????? cout << "學習編程需要熱情,更需要理性!我和您一樣,也在這個年齡段!"<< endl;

?? else if(age < 45)

????? cout << "活到老,學到老!何況您還未老。殺毒王王江民,不也在這個時候才開始學習電腦嗎?" << endl;

?? else

????? cout <<? "前輩,只要您像學書法一樣潛心學編程!您一定會有收獲!" << endl;

}

//---------------------------------------------------------------------------
 

 

//Unit2.h 的主要代碼:

 

//聲明OutAgeText()函數,供Unit1.cpp使用

void OutAgeText();

//---------------------------------------------------------------------------
 

請大家完成這個工程,直到能正確運行。

 

現在我們得到一個印象:當我們定義了一個函數或變量之后,似乎所有的源代碼文件中都可以使用它,只要你在使用之前寫一下相應的聲明。

這樣會不會帶來麻煩了?想象一下,你在A文件定義了一個變量: int i, 那么以后你在別的文件里就不能再定義這個變量了!原因前面已經說過,編譯器(或鏈接器)會說有兩個變量重名。函數也一樣,盡管它有重載機制,便那也只能是有限制地允許函數重名。

 

事實上,上例中的 int age 是一個全局變量。關于“全局”的解釋,需要引起C,C++程序的另一話題:作用范圍。這是下一章的內容。在那一章里,我們將看到,大部分變量只在它一定的作用范圍內“生存”,不同的作用范圍的變量就可以毫無障礙地重名了。

休息休息(該點眼藥水了···),然后學習本章附加一節。

轉載于:https://www.cnblogs.com/west2007/archive/2009/09/08/1562399.html

總結

以上是生活随笔為你收集整理的c++的程序的文件结构的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 高潮喷水一区二区三区 | 天天舔天天射 | 中国三级视频 | 免费男女乱淫真视频免费播放 | 欧美亚洲中文精品字幕 | 成人黄色免费网址 | 你懂的国产 | caoporn人人| 波多野结衣视频一区 | 闷骚老干部cao个爽 av九九九 | 一区二区三区四区五区六区 | 男男全肉变态重口高h | 欧美专区 日韩专区 | 日韩综合网站 | 久久精品国产亚洲AV成人雅虎 | 亚洲av激情无码专区在线播放 | 毛片大片 | 一区二区三区四区精品 | 51精品国自产在线 | 国精品无码人妻一区二区三区 | 国产精品久久久久久69 | 成年人毛片视频 | 成人a v视频 | 欧美aaa大片 | 亚洲福利久久 | 久久久久成人精品免费播放动漫 | 色综合视频在线观看 | 黑人精品欧美一区二区蜜桃 | 日本在线视频中文字幕 | 亚洲av中文无码乱人伦在线视色 | 国产日韩视频在线观看 | 国产黄a三级三级看三级 | 黄色裸体视频 | 奇米影视中文字幕 | 日本一级片免费看 | 国产第八页| 精品成人一区二区三区久久精品 | 国产精品美女高潮无套 | 91色吧 | 人妻射精一区二区 | 欧美乱妇狂野欧美视频 | 樱桃视频一区二区三区 | 欧美一区,二区 | av在线视屏 | 男女天堂av | 激情专区 | 国产欧美日韩在线播放 | 在线免费精品 | 九九在线观看视频 | av在线激情 | 精品久久久久国产 | 成人在线免费视频 | av资源导航 | 99久久久无码国产精品 | 国产又黄又粗又爽 | 人人妻人人澡人人爽国产一区 | 人人看超碰| 精品久久久久久无码国产 | 五月丁香久久婷婷 | 小嫩嫩精品导航 | 丰满熟妇乱又伦 | 伊人久久在线 | 我和岳m愉情xxxⅹ视频 | 国产视频中文字幕 | 亚洲天堂中文 | 91麻豆网 | 欧美在线播放 | 人人澡人人澡 | 性色av无码久久一区二区三区 | 国产69精品久久久 | 超碰伦理 | 朝桐光av在线| 国产精品人成在线观看免费 | 在线视频一区二区 | 六月丁香激情综合 | 三上悠亚三级 | 好吊视频一区二区三区 | 天天撸天天操 | 国产精品久久久99 | av导航网址 | 三上悠亚激情av一区二区三区 | 96日本xxxxxⅹxxx17 | 亚洲成av人影院 | 女色综合 | 青娱乐国产精品 | 免费成人在线视频观看 | 暗呦丨小u女国产精品 | 久久久美女视频 | 国产黄色免费看 | 成人午夜天 | 国产剧情av引诱维修工 | 国产毛片在线视频 | 久久只有这里有精品 | 97精品视频在线 | 国产亚洲精品久久久久久久 | 一区二区日韩精品 | 在线观看欧美一区 | 亚洲福利视频网 | 欧美激情伊人 |