作為一個二手的.net程式員,你看到了c++頭檔案一定就犯迷糊了,這到底是個啥玩意。再我糾結了24個小時, google20次,度娘10下,看過10來騙文章以後,我可能稍微開竅了。我對c++頭檔案總結,與.net比較如下:
一、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;
(3)函數和類結構聲明等。
至于函數和類 結構的聲明,這裡真的不用進行過多的贅述。你了解為接口聲明,在源檔案中實作就ok了。
對頭檔案說了這麼多,也做與.net比較。我們一句話來總結,。net其實是有頭檔案的,隻不過分散在各個單獨的檔案中,而c++把這些内容集中在一起了。