1. 程式人生 > >標頭檔案、預處理命令、名稱空間(作用域)、連結

標頭檔案、預處理命令、名稱空間(作用域)、連結

關於與include搭配的符號(雙引號 & 尖括號):

  C++有一些編寫好的標頭檔案(比如標準函式庫等等),它們存放在VC++的Include資料夾裡。當我們使用#include <檔名>命令時,編譯器就到這個資料夾裡去找對應的檔案。用這種寫法去包含一個我們自己編寫的標頭檔案(不在那個Include資料夾裡)就會出錯了。所以包含C++提供的標頭檔案時,應該使用尖括號。

  #include "檔名"命令則是先在當前檔案所在的目錄搜尋是否有符合的檔案,如果沒有再到Include資料夾裡去找對應的檔案。因此,無論這個檔案是C++提供的還是自己編寫的,使用#include "檔名"命令一定是正確的。但系統的標頭檔案最好還是用尖括號,那樣可以加快搜索速度。

小節

雙引號定義從當前檔案目錄下進行查詢,雙尖括號定義從標準庫目錄開始查詢。如果不是自己的標頭檔案,就用尖括號,這樣可以加快搜索的速度;如果是自己的標頭檔案,就用雙引號。

關於標頭檔案裡寫的的內容

標頭檔案是一些以.h作為副檔名的標準文字檔案。一般情況下,都應該把自定義的標頭檔案和其餘的程式檔案放在同一個子目錄裡,或者在主程式目錄下專門建立一個子資料夾來集中存放它們。

可以用標頭檔案來儲存程式的任何一段程式碼,如函式和類的宣告,但一定不要用標頭檔案來儲存它們的實現。

與標準的C++原始碼檔案相比,在標頭檔案裡應該使用更多的註釋。至少把它的用途和用法描述清楚

應該在註釋裡說明的內容包括:建立日期、檔案用途、建立者姓名、最後一次修改日期、有什麼限制和前提條件等等。標頭檔案裡的每以一個類和函式也應該有說明。

標頭檔案典型的做法是隻用它們來儲存函式宣告、使用者自定義型別資料(結構和類)、模板和全域性性的常量。

如果你有一個程式需要多次呼叫一個或一組函式,或是你有一個或一組函式需要在多個程式裡呼叫,就應該把它們的宣告拿出來放到一個頭檔案裡。
標頭檔案應該只包含
最必要的程式碼,比如只宣告一個類或只包含一組彼此相關的函式

小節

多寫些註釋,對於類和函式只寫宣告不寫實現。

寫的內容->函式宣告、使用者自定義型別資料(結構和類)、模板和全域性性的常量

內容的用途->多次呼叫的一個或一組函式、一個或一組函式需要在多個程式裡呼叫

帶目錄的標頭檔案:

include時,雙引號裡,

【.\SRC\】 這樣寫表示,當前目錄中的SRC資料夾,還可以直接寫【SRC\】;

..\SRC\】這樣寫表示,當前目錄的上一層目錄中SRC資料夾;
【..\..\SRC\】 這樣寫表示,當前目錄的上兩層目錄中SRC資料夾;

要是不用上面這種寫法,就是在專案屬性的附加目錄裡新增所有需要包含檔案的目錄。

預處理命令:


預處理用法:

#if FLAG
    //程式碼
    //程式碼
    //程式碼
    //程式碼
#endif

FLAG為0,就不執行裡面的程式碼;要是為1,就執行裡面的程式碼。

這個最大的功能就是用來裁剪功能

把功能模組放到這個結構裡,裁剪時,FLAG置0,則為裁剪;FLAG置1,則為保留。

這個用法一般是在系統裁剪時使用,當看過系統級原始碼時,就知道這個有多棒了!

FLAG就是給外面的介面,用來控制是否裁剪。

這篇文章就舉例子說明的這個用法。

#ifndef LOVE_FISHC
#define LOVE_FISHC
class Rational{ … };
#endif

ifndef先判斷後面的字元是否定義過,如果沒定義,就在下面定義一下。如果已經定義了,就不執行裡面的程式碼。

這樣就利用這個字元來探測是否重定義了。

這個字元的命名規則:將原標頭檔案名字母都變大寫,實心點用下劃線代替。例:【Halcon.h -> HALCON_H】

名稱空間(作用域):

最大的區域是全域性作用域,最小的區域是一個程式碼塊。例如:

{
      int a = 20;
}
//a在此處已經不存在了
如果沒有名稱空間,且工程很龐大,因為沒有兩樣東西可以有同樣的名字,只能通過詳細的命名描述加以區分。

這個時候就正好使用名稱空間。使變數只在名稱空間內是獨一無二的就ok.建立格式如下:

namespace myNamespace
{
// 全部東西
}
注意,結尾不加分號,這不是結構不是類。

例如,通過這樣,可以把兩個person區分開,只要加上各自的名稱空間就可以在同一個作用域使用啦~

namespace author
{
std::string person;
}
namespace programmer
{
std::string person;
}

具體用法:

把.h檔案中程式碼用namespace括起來(注意,不要括進去預處理程式碼),把.cpp檔案中程式碼也用namespace括起來(同前面一樣,不要括進去預處理程式碼)。

最後在呼叫這個.h的cpp裡,在前面宣告一下using namespace xxx【其實是不推薦這麼用的,要是這麼用,就失去了使用名稱空間的意義了

正確的用法是,在呼叫這個.h的cpp裡,使用這樣的格式:【(名稱空間的名)::(變數或函式

其實這個名稱空間的使用,有三種:例)

1. std::cout << "xxx" << std::endl;   //哪裡使用,就在哪裡新增名稱空間的標識

2. using namespace std;           //直接在include下一行寫,不推薦這麼用,失去名稱空間的意義了

3. using std::cout;             //直接在include下一行寫,

  cout << "xxx" << std::endl;     (要使用哪個變數或函式,就提取出來哪個

                         cout提取了,但endl沒提取,所以cout不需要std字首,而endl仍需要。

關於連結:

查資料的時候,有這麼幾個文章講得很好,還很仔細,但臨時時間不夠,留著以後再看。

12月3號再整理成文字。

---------------------------------------------------------------------------------------------------

提到連結性,就要把儲存持續性和作用域也拎出來。

下面這一張圖,就說清了這三個概念之間的關係。


自動:存在於程式碼塊中,就是區域性變數。比如在一個函式體裡宣告的變數,函式執行結束後就自動釋放了,記憶體自動歸還給系統。

暫存器:還沒到控制這種變數的水平和場合,沒研究。~~~哈哈哈

靜態,無連結性:這種就還是區域性變數。也是比如在函式體裡宣告的static字首的變數,外面不能用,也就沒有外部連結性。然後變數本身就在程式碼塊內部,也不涉及到內部連結性。so,無連結性。靜態無連結性的變數,只在該程式碼塊中可用,但好處是,這種變數在該程式碼塊不處於活動狀態時仍存在。【這個型別是加了static的】

靜態,外部連結性:宣告的地方就不在程式碼塊裡了,而是在檔案中。例如在.cpp或者是.h中,宣告一下變數,也不加static,這樣就擁有外部連結性了。其實這個變數在檔案內部裡都能用,就屬於是全域性變量了。而所謂的外部,就是在其他檔案中使用,比如在哪個檔案中使用,就在那個檔案中用extern再宣告一下這個變數就ok啦。(測試過,用extern宣告的話,不用包含對應標頭檔案,直接extern宣告一下,就能用。)【這個型別是不加static的】

靜態,內部連結性:宣告的地方還是不再程式碼塊裡,應該在檔案中,和上面那種外部連結性的是在一個位置宣告的。只是,這個前面加一個static字首,這樣就有內部連結性了。外面檔案不能使用這個變量了,就是extern也不行了。靜態內部連結性extern不行的時候,使用include包含.h就ok了,這樣就可以使用別的檔案中的靜態內連結變量了。static字首就是為了使這種位置的變數具有內部連結性。【這個型別是加了static的

差點兒忘說一個事兒,當外部變數和區域性變數衝突的時候(也就是同名,同類型),外部變數會暫時被區域性變數覆蓋(就跟函式被過載了似的)。等區域性程式碼塊執行結束後,又恢復到了外部變數。此刻區域性的那個變數已經被釋放了,此刻只剩下這個外部變數還在記憶體中了。

還有const的事兒,如果宣告的靜態外部連結性的變數前面有const,那會秒變內部連結性,因為const自帶static屬性。但如果非要外部用,可以在初始化宣告的時候,最前面加個extern。注意!!!是初始化宣告的時候,就加extern。然後在要用這個變數的其他檔案中,就正常加上extern宣告就行了,不用初始化,因為一定初始化過了。