一、C++標頭檔究竟是什麼,你怎麼看?
每個C++/C程式通常分為兩個檔案。一個檔案用於儲存程式的聲明(declaration),稱為標頭檔。另一個檔案用於儲存程式的實現(implementation),稱為定義(definition)檔案。C++/C程式的標頭檔以“.h”為尾碼,C程式的定義檔案以“.c”為尾碼,C++程式的定義檔案通常以“.cpp”為尾碼(像linux等系統以“.cc”或“.cxx”為尾碼)。簡而言之,就是用於聲明的檔案。
那作為.net的程式員我們,我們會問這個問題,C#中的標頭檔,你怎麼看?
c#中聲明和定義在一個地方,相當於把標頭檔放在執行檔案中。 一般引用時,只需要用using引入命名空間即可。對於我們.net程式員可以這麼理解,標頭檔是相當於命名空間的定義,引入以後,就相當於引入命名空間。我們.net中直接是引入命名空間的。
二、C++標頭檔到底是哪些內容,你怎麼看?
標頭檔由三部分內容組成:
(1)標頭檔開頭處的著作權和版本聲明
這部分有分結構具體如下:
①著作權資訊。②檔案名稱,標識符,摘要。③目前的版本號,作者/修改者,完成日期。④版本曆史資訊。
我們.net中有不有這類似的結構,你怎麼看啊?有啊,AssemblyInfo.cs不就是詳細的記錄這些資訊嗎。
(2)預先處理塊。
來瞧一瞧預先處理塊。作為.net程式員的我們,你是不是對於預先處理塊,聞所未聞。 他的意思非常的簡單,在編譯之前進行的處理。C++編譯器中有一個前置處理器,我們.net中並沒有一個單獨的預先處理的概念。他有分成了3個階段:
2.檔案包含;3.條件編譯。
什麼是宏定義,
1.不帶參數的宏定義:
宏定義又稱為宏代換、宏替換,簡稱“宏”。格式:#define 標識符 字串其中的標識符就是所謂的符號常量,也稱為“宏名”。預先處理(先行編譯)工作也叫做宏展開:將宏名替換為字串。 掌握"宏"概念的關鍵是“換”。一切以換為前提、做任何事情之前先要換,準確理解之前就要“換”。
對於不帶參數的宏的說明如下:
(1)宏名一般用大寫;(2)使用宏可提高程式的通用性和易讀性,減少不一致性,減少輸入錯誤和便於修改。例如:數組大小常用宏定義;(3)預先處理是在編譯之前的處理,而編譯工作的任務之一就是語法檢查,預先處理不做語法檢查。;(4)宏定義末尾不加分號;(5)宏定義寫在函數的花括弧外邊,範圍為其後的程式,通常在檔案的最開頭。 (6)可以用#undef命令終止宏定義的範圍 (7)宏定義可以嵌套(8)字串" "中永遠不包含宏(9)宏定義不分配記憶體,變數定義分配記憶體。
2.帶參數的宏:
除了一般的字串替換,還要做參數代換格式:#define 宏名(參數表) 字串
帶參數的宏的說明:
(1)實參如果是運算式容易出問題
#define S(r) r*r
area=S(a+b);第一步換為area=r*r;,第二步被換為area=a+b*a+b;
正確的宏定義是#define S(r) (r)*(r);
(2)宏名和參數的括弧間不能有空格 ;
(3)宏替換隻作替換,不做計算,不做運算式求解;
(4)函數調用在編譯後程式運行時進行,並且分配記憶體。宏替換在編譯前進行,不分配記憶體;
(5)宏的啞實結合不存在類型,也沒有類型轉換。
(6)函數只有一個傳回值,利用宏則可以設法得到多個值;
(7)宏展開使來源程式變長,函數調用不會;
(8)宏展開不佔已耗用時間,只佔編譯時間,函數調用占已耗用時間(分配記憶體、保留現場、值傳遞、傳回值)
說了這麼多C++的宏定義,我們.net是不是支援宏了,答案是肯定的。 可以使用以上的define的關鍵字可以實現C++的宏已定義流程,一般是在類的頭部的聲明。
二檔案包含——一個檔案包含另一個檔案的內容
格式:
#include "檔案名稱" 或#include <檔案名稱>
編譯時間以包含處理以後的檔案為編譯模組,被包含的檔案是源檔案的一部分。編譯以後只得到一個目標檔案.obj,被包含的檔案又被稱為“標題檔案”或“頭部檔案”、“標頭檔”,並且常用.h作副檔名。修改標頭檔後所有包含該檔案的檔案都要重新編譯,標頭檔的內容除了函數原型和宏定義外,還可以有結構體定義,全域變數定義:(1)一個#include命令指定一個標頭檔;(2)檔案1包含檔案2,檔案2用到檔案3,則檔案3的包含命令#include應放在檔案1的頭部第一行;(3)包含可以嵌套;(4)<檔案名稱>稱為標準方式,系統到標頭檔目錄尋找檔案,"檔案名稱"則先在目前的目錄尋找,而後到標頭檔目錄尋找;(5)被包含檔案中的靜態全域變數不用在包含檔案中聲明。
說道這裡,我們.net是不是也有檔案包含的概念了,怎麼沒有了,你using 命名空間,不就是最好的.net檔案包含體現了。他編譯以後也是.obj檔案。
三 條件編譯—— 有些語句行希望在條件滿足時才編譯。
格式:(1)#ifdef 標識符 程式段1#else程式段2#endif或#ifdef程式段1 #endif當標識符已經定義時,程式段1才參加編譯。格式:(2)#ifndef 標識符 格式:(3) #if 運算式1 程式段1 #else程式段2#endif
當運算式1成立時,編譯器段1,當不成立時,編譯器段2。使用條件編譯可以使目標程式變小,已耗用時間變短。先行編譯使問題或演算法的解決方案增多,有助於我們選擇合適的解決方案。此外,還有布局控制:#progma,這也是我們應用預先處理的一個重要方面,主要功能是為編譯器提供非常規的控制流程資訊
.net中也有他的條件編譯的,無非也是一下的處理格式:
#if #elif #else #endif;
只不過,我們平時項目中很少用罷了,要學習的他的具體的部落格詳見:
http://www.jb51.net/article/31701.htm
(3)函數和類結構聲明等。
至於函數和類 結構的聲明,這裡真的不用進行過多的贅述。你理解為介面聲明,在源檔案中實現就ok了。
對標頭檔說了這麼多,也做與.net比較。我們一句話來總結,。net其實是有標頭檔的,只不過分散在各個單獨的檔案中,而C++把這些內容集中在一起了。