原文地址:https://blog.csdn.net/qzx9059/article/details/89210571ios
c++中 cpp和hpp
咱們能夠將全部東西都放在一個.cpp文件內,編譯器會將這個.cpp編譯成.obj,即編譯單元。一個程序能夠由一個編譯單元組成,也能夠由多個編譯單元組成。一個.cpp對應一個.obj,而後將全部的.obj連接起來(經過一個叫連接器的程序),組成一個.exe,即程序。若是一個.cpp要用到另外一個.cpp定義的函數怎麼辦,只需在這個.cpp中寫上它的函數聲明。 連接器將全部的obj連接起來,可是若是碰巧有相同的函數或外部變量怎麼辦?C++能夠經過一種叫作連接屬性的關鍵字來限定,某個函數是屬於整個程序公用的,仍是隻在一個編譯單元obj裏面使用,這些關鍵字就是extern(外部連接)和static(內部連接)。讓咱們說說.h。其實沒有.h,程序也能很好的工做,可是當你發現一個外部連接的函數或外部變量,須要許多分聲明,由於只要使用到該函數的單元,就必須寫一份聲明在那個.cpp裏面,若是要修改會很麻煩!!!.h就是爲了解決這個問題而誕生的,它包含了這些公共的東西,而後全部須要使用該函數的.cpp,只須要用#include包含進去即可,之後須要修改,只是修改一分內容。#include並非什麼申請指令,只是將指定文件的內容,原封不動的拷貝進來。
不是很嚴格的講,.h文件作的是類的聲明,包括類成員的定義和函數的聲明,而.cpp文件作的類成員函數的具體實現(定義)。一個*.h文件和*.cpp文件通常是配對的。在*.cpp文件的第一行通常也是#include".h"文件,其實也至關於把.h文件裏的東西複製到*.cpp文件的開頭。因此,你所有寫在*.cpp文件其實也是同樣的。
既然能夠直接寫cpp,爲何還要寫hpp?除了編程規範外,還涉及到類一個重要性質,就是封裝性。好比如今咱們公司和另外一家軟件公司合做,這樣就必然要互相提供一些軟件的信息(好比一些類,它究竟是要作什麼的),但是在提供這些信息的同時咱們又不像讓對方知道咱們這些類的具體實現,畢竟這些是咱們公司的算法核心和心血啊。因此這個時候就能夠把類的接口(這個類是要作什麼的)放在*.h文件中,而具體類的實現放在 .cpp文件。這時候咱們只要給對方公司.h文件就好了。這樣既提供了必要的信息,又保護了咱們的核心代碼。
1.最表面的機制是:頭文件是程序的界面(是代碼界面),提供給程序員以 類、模版、函數等一系列的聲明,讓程序員知道應該怎麼調用裏面的「東西」。
2.從動態連接庫的角度看:頭文件提供界面,使得程序員在須要加載一個庫函數的時候(這裏也僅僅是舉簡單的例子)查看頭文件就知道怎麼加載這個動態庫內部的函數。
3.從軟件的擴展來講:將頭文件做爲界面,再去定義它的實現,這樣只要保證界面不變(頭文件不變),就能夠只修改實現文件,而沒必要修改其餘的實現代碼。好比你有一個sort()函數來排序,在一個大程序中,你後來發現這個sort()有更好的算法,因而你只須要去修改函數的實現(修改.cpp文件的sort()函數的代碼),其餘使用這個函數的地方能夠徹底保持不變,這是分割技術的第一個好處
4.從編譯的角度看:
全部源文件都是被編譯器分別劃分單元來分別編譯,在編譯的過程當中,頭文件被嵌入到實現文件裏面一塊兒做爲一個編譯單元被編譯(實現文件filename.cpp裏的#include "filename.h"這一行被替換成filename.h裏面的全部內容(實際上會把預處理指令去掉,這纔是預處理最本質的做用))。
舉一個簡單的例子,你定義了sort()函數,在test.h頭文件裏聲明,在test.cpp裏定義,這個時候在test.cpp裏面#include 「test.h」,並定義sort()函數。
你須要在頭文件內部寫預處理代碼
頭文件的全部內容,都必須包含在
#ifndef {Filename}
#define {Filename}
12
//{Content of head file} 你的代碼寫在這裏
#endif
這樣才能保證頭文件被多個其餘文件引用(include)時,內部的數據不會被屢次定義而形成錯誤。
c++中頭文件(.h)和源文件(.cpp)都應該寫些什麼?
頭文件(.h):
寫類的聲明(包括類裏面的成員和方法的聲明)、函數原型、#define常數等,但通常來講不寫出具體實現。
頭文件還能夠定義:在編譯的時候就已知道其值的cosnt對象和inline 函數。在頭文件中定義上述實體,是由於編譯器須要它們的定義來產生代碼。
源文件(.cpp):
源文件主要寫實現頭文件中已經聲明的那些函數的具體代碼。須要注意的是,開頭必須#include一下實現的頭文件,以及要用到的頭文件。那麼當你須要用到本身寫的頭文件中的類時,只須要#include進來就好了。
下面舉個最簡單的例子來描述一下,咱就求個圓面積。
第1步,創建一個空工程(以在VS2003環境下爲例)。
第2步,在頭文件的文件夾裏新建一個名爲Circle.h的頭文件,它的內容以下:
#ifndef CIRCLE_H
#define CIRCLE_H
class Circle
{
private:
double r;//半徑
public:
Circle();//構造函數
Circle(double R);//構造函數
double Area();//求面積函數
};
#endif
12345678910111213141516
注意到開頭結尾的預編譯語句。在頭文件裏,並不寫出函數的具體實現。
第3步,要給出Circle類的具體實現,所以,在源文件夾裏新建一個Circle.cpp的文件,它的內容以下:
#include "Circle.h"
Circle::Circle()
{
this->r=5.0;
}
Circle::Circle(double R)
{
this->r=R;
}
double Circle:: Area()
{
return 3.14*r*r;
}
123456789101112131415161718
須要注意的是:開頭處包含了Circle.h,事實上,只要此cpp文件用到的文件,都要包含進來!這個文件的名字其實不必定要叫Circle.cpp,但很是建議cpp文件與頭文件相對應。
最後,咱們建一個main.cpp來測試咱們寫的Circle類,它的內容以下:
#include <iostream>
#include "Circle.h"
using namespace std;
int main()
{
Circle c(3);
cout<<"Area="<<c.Area()<<endl;
return 1;
}
注意到開頭時有#include "Circle.h"的聲明,證實咱們使用到了咱們剛纔寫的Circle類。
1234567891011
至此,咱們工程的結構爲:
注意這裏聲明與定義的區別:它們最本質的區別是定義只能夠出現一次,聲明能夠出現屢次。聲明不分配空間,而定義是要分配空間的。 ———————————————— 版權聲明:本文爲CSDN博主「輕遠清清」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。 原文連接:https://blog.csdn.net/qzx9059/article/details/89210571