C++學習(七)頭文件和源文件的關係【轉】

今天找了個解析xml的開源C++項目tinyxml,按照網上的說法去編譯,可是一直編譯不經過,「沒法打開頭文件tinyxml.h」,可是明明我在工程底下有了這個文件,對於我這種初學C++的人來講我並不知道頭文件和源文件到底什麼關係(不像java的類文件),不過最終仍是解決了這個問題。java

1、源文件如何根據#include來關聯頭文件 
1,系統自帶的頭文件用尖括號括起來,這樣編譯器會在系統文件目錄下查找。 
#include 
2,用戶自定義的文件用雙引號括起來,編譯器首先會在用戶目錄下查找,而後在到C++安裝目錄(好比VC中能夠指定和修改庫文件查找路徑,Unix和Linux中能夠經過環境變量來設定)中查找,最後在系統文件中查找。 
#include 「"xxx.h」(我一直覺得」」和<>沒什麼區別,可是tinyxml.h是非系統下的都文件,因此要用」」) 
2、頭文件如何來關聯源文件 
    這個問題其實是說,已知頭文件「a.h」聲明瞭一系列函數,「b.cpp」中實現了這些函數,那麼若是我想在「c.cpp」中使用「a.h」中聲明的這些在「b.cpp」中實現的函數,一般都是在「c.cpp」中使用#include 「a.h」,那麼c.cpp是怎樣找到b.cpp中的實現呢? 
    其實.cpp和.h文件名稱沒有任何直接關係,不少編譯器均可以接受其餘擴展名。好比偶如今看到偶們公司的源代碼,.cpp文件由.cc文件替代了。 
    在Turbo C中,採用命令行方式進行編譯,命令行參數爲文件的名稱,默認的是.cpp和.h,可是也能夠自定義爲.xxx等等。 
    譚浩強老師的《C程序設計》一書中提到,編譯器預處理時,要對#include命令進行「文件包含處理」:將file2.c的所有內容複製到#include 「file2.c」處。這也正說明了,爲何不少編譯器並不care到底這個文件的後綴名是什麼----由於#include預處理就是完成了一個「複製並插入代碼」的工做。 
    編譯的時候,並不會去找b.cpp文件中的函數實現,只有在link的時候才進行這個工做。咱們在b.cpp或c.cpp中用#include 「a.h」其實是引入相關聲明,使得編譯能夠經過,程序並不關心實現是在哪裏,是怎麼實現的。源文件編譯後成生了目標文件(.o或.obj文件),目標文件中,這些函數和變量就視做一個個符號。在link的時候,須要在makefile裏面說明須要鏈接哪一個.o或.obj文件(在這裏是b.cpp生成的.o或.obj文件),此時,鏈接器會去這個.o或.obj文件中找在b.cpp中實現的函數,再把他們build到makefile中指定的那個能夠執行文件中。 
    在Unix下,甚至能夠不在源文件中包括頭文件,只須要在makefile中指名便可(不過這樣大大下降了程序可讀性,是個很差的習慣哦^_^)。在VC中,一幫狀況下不須要本身寫makefile,只須要將須要的文件都包括在project中,VC會自動幫你把makefile寫好。 
    一般,編譯器會在每一個.o或.obj文件中都去找一下所須要的符號,而不是隻在某個文件中找或者說找到一個就不找了。所以,若是在幾個不一樣文件中實現了同一個函數,或者定義了同一個全局變量,連接的時候就會提示「redefined」。 
1、聲明與定義的區分: 
一個聲明就是一個定義,除非 : 
聲明:引入名稱 
定義:引入實體 
1.它聲明瞭一個沒有詳細說明函數體的函數 
2.它包含一個extern定義符且沒有初始化函數或函數體 
3.它是一個包含在一個類定義以內的靜態類數據成員的聲明,它必須在最終程序的某處準確的定義一次 
4.它是一個類名聲明,如class test; 
5.它是一個typedef聲明。 
言外之意: 
1。類的聲明也就是定義 
2。同時賦初值的聲明也就是定義,如int a=2; 
3。類非靜態數據成員的聲明也就是定義??? 
4。類的全部成員函數的聲明也就是定義 
一個定義就是一個聲明,除非: 
1.它定義的是一個靜態數據成員 
2.它定義了一個非內聯成員函數 
內部鏈接和外部鏈接: 
編譯時每一個文件會被編譯成一個含有必要信息的源文件(又叫編譯單元),而後編譯單元會聯結成一個和族文件同名的.o文件,.o文件把不一樣的編譯單元中產生的符號聯繫起來,構成一個可執行文件。有兩種大相徑庭的連接:內部的和外部的,將這些編譯單元聯繫起來。 
內部鏈接:對這個定義的訪問被侷限在當前編譯單元,其餘編譯單元沒法訪問。 
外部鏈接:可被其餘單元訪問,所以名稱在整個執行文件中必須惟一。 
類的定義(同時也是聲明),enum,struct,都是內部鏈接,內聯函數,靜態的非類成員數據也是 
typedef聲明的類型也是內聯結。 
非內聯成員函數(包括靜態成員)有外部鏈接,非內聯函數,非靜態自由函數(非類的成員函數)也是外鏈接。 
聲明只對當前編譯單元有用,他們不會影響到.o文件, 
.h文件,因爲該文件會被其餘.cpp文件包含,但因爲聲明只是對當前編譯單元有效,是不會將符號引入.o文件,因此該文件不能含有任何外部鏈接的符號(數據成員和函數)的定義。通常狀況下也不要包含內鏈接符號的定義。 
綜上所訴: 
.h文件中能包含: 
1。類成員數據的聲明,但不能賦值 
2.類靜態數據成員的定義和賦值,但不建議,只是個聲明就好。 
3。類的成員函數的聲明 
4。非類成員函數的聲明 
5.常數的定義:如:const int a=5; 
6.靜態函數的定義 
7.類的內聯函數的定義 
不能包含: 
1. 全部非靜態變量(不是類的數據成員)的聲明 
2。 默認命名空間聲明不要放在頭文件,using namespace std;等應放在.cpp中,在.h文件中使用std::string函數

相關文章
相關標籤/搜索