C++中的頭文件和源文件

一、C++編譯模式???????

?????? ?通常,在一個C++程序中,只包含兩類文件——cpp文件和h文件。cpp文件被稱作C++源文件,里面放的都是C++的源代碼;h文件則被稱作C++頭文件,里面放的也是C++的源代碼。

??????? C+ +語言支持“分別編譯”(separate compilation)。也就是說,一個程序所有的內容,可以分成不同的部分分別放在不同的.cpp文件里。

??????? cpp文件里的東西都是相對獨立的,在編譯(compile)時不需要與其他文件互通,只需要在編譯成目標文件后再與其他的目標文件做一次鏈接(link)就行了。比如,在文件a.cpp中定義了一個全局函數“void a() {}”,而在文件b.cpp中需要調用這個函數。即使這樣,文件a.cpp和文件b.cpp并不需要相互知道對方的存在,而是可以分別地對它們進行編譯, 編譯成目標文件之后再鏈接,整個程序就可以運行了。

?

二、C++頭文件

??????? 頭文件的內容跟.cpp文件中的內容一樣,都是C++源代碼。但頭文件不用被編譯。

??????? 我們把所有的函數聲明全部放進一個頭文件中,當某一個cpp源文件需要它們時,它們就可以通過一個宏命令“#include”包含進這個cpp文件中,從而把它們的內容合并到cpp文件中去。當cpp文件被編譯時,這些被包含進去的h文件的作用便發揮了。

???????? #include的作用是把它后面所寫的那個文件的內容,完完整整地、一字不改地包含到當前的文件中來。值得一提的是,它本身是沒有其它任何作用與副功能的,它的作用就是把每一個它出現的地方,替換成它后面所寫的那個文件的內容。簡單的文本替換,別無其他。因此,main.cpp文件中的第一句(#include "math.h"),在編譯之前就會被替換成math.h文件的內容。即在編譯過程將要開始的時候,main.cpp的內容已經發生了改變

?

三、頭文件的書寫

??????? 1、頭文件中,只能存在變量或者函數的聲明,而不要放定義。

??????? 因為一個頭文件的內容實際上是會被引入到多個不同的cpp文件中的,并且它們都會被編譯。放聲明當然沒事,如果放了定義,那么也就相當于在多個文件中出現了對于一個符號(變量或函數)的定義,縱然這些定義都是相同的,但對于編譯器來說,這樣做不合法。

??????? 2、頭文件中可以寫const對象的定義。

??????? 因為全局的const對象默認是沒有extern的聲明的,所以它只在當前文件中有效。把這樣的對象寫進頭文件中,即使它被包含到其他多個cpp文件中,這個對象也都只在包含它的那個文件中有效,對其他文件來說是不可見的,所以便不會導致多重定義。同時,因為這些cpp文件中的該對象都是從一個頭文件中包含進去的,這樣也就保證了這些cpp文件中的這個const對象的值是相同的,可謂一舉兩得。

???????? 同理,static對象的定義也可以放進頭文件。

????????3、頭文件中可以寫內聯函數(inline)的定義。

????????inline函數是需要編譯器在遇到它的地方根據它的定義把它內聯展開的,而并非是普通函數那樣可以先聲明再鏈接的(內聯函數不會鏈接),所以編譯器就需要在編譯時看到內聯函數的完整定義才行。

??????? 如果內聯函數像普通函數一樣只能定義一次的話,這事兒就難辦了。因為在一個文件中還好,我可以把內聯函數的定義寫在最開始,這樣可以保證后面使用的時候都可以見到定義;但是,如果我在其他的文件中還使用到了這個函數那怎么辦呢?這幾乎沒什么太好的解決辦法。

??????? 因此C++規定,內聯函數可以在程序中定義多次,只要內聯函數在一個cpp文件中只出現一次,并且在所有的cpp文件中,這個內聯函數的定義是一樣的,就能通過編譯。那么顯然,把內聯函數的定義放進一個頭文件中是非常明智的做法。

??????? 4、頭文件中可以寫類(class)的定義。

???????? 在程序中創建一個類的對象時,編譯器只有在這個類的定義完全可見的情況下,才能知道這個類的對象應該如何布局,所以,關于類的定義的要求,跟內聯函數是基本一樣的。所以把類的定義放進頭文件,在使用到這個類的.cpp文件中去包含這個頭文件,是一個很好的做法。

??????? 值得一提的是,類的定義中包含著數據成員和函數成員。數據成員是要等到具體的對象被創建時才會被定義(分配空間),但函數成員卻是需要在一開始就被定義的,這也就是我們通常所說的類的實現。

??????? 一般的做法是,把類的定義放在頭文件中,而把函數成員的實現代碼放在一個cpp文件中。這是很好的辦法。

??????? 還有另一種辦法,即直接把函數成員的實現代碼也寫進類定義里面。在C++的類中,如果函數成員在類的定義體中被定義,那么編譯器會視這個函數為內聯的。因此,把函數成員的定義寫進類定義體,一起放進頭文件中,是合法的。

??????? 注意一下,如果把函數成員的定義寫在類定義的頭文件中,而沒有寫進類定義中,這是不合法的,因為這個函數成員此時就不是內聯的了。一旦頭文件被兩個或兩個以上的cpp文件包含,這個函數成員就被重定義了。

?????? 5、頭文件需要保護措施

??????? 如果頭文件中只包含聲明語句,那么它被同一個cpp文件包含再多次都沒問題。但如果頭文件是上述中某種情況,定義了一些函數,在cpp文件中包含了兩次頭文件就麻煩了。

??????? 使用"#define"配合條件編譯可以很好地解決這個問題。在一個頭文件中,通過#define定義一個名字,并且通過條件編譯#ifndef...#endif使得編譯器可以根據這個名字是否被定義,再決定要不要繼續編譯該頭文中后續的內容。這個方法雖然簡單,但是寫頭文件時一定記得寫進去。


轉載自:http://www.cnblogs.com/lidabo/archive/2012/04/17/2454568.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/258165.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/258165.shtml
英文地址,請注明出處:http://en.pswp.cn/news/258165.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Hibernate 事物隔離級別 深入探究

目錄 一、數據庫事務的定義 二、數據庫事務并發可能帶來的問題 三、數據庫事務隔離級別 四、使用Hibernate設置數據庫隔離級別 五、使用悲觀鎖解決事務并發問題 六、使用樂觀鎖解決事務并發問題 Hibernate事務與并發問題處理(樂觀鎖與悲觀鎖) 一、數據庫…

Linked List Cycle II - LeetCode

Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Note: Do not modify the linked list. Follow up:Can you solve it without using extra space? 思路:維護兩個指針slow和fast。先判斷是否存在環。 在判斷是否…

mysql 無論輸入什么都是現實 not found_NotAPanda

前言面試競爭力越來越大,是時候擼一波Vue和React源碼啦;本文從20個層面來對比Vue和React的源碼區別;如果需要了解API的區別,請戳:Vue 開發必須知道的 36 個技巧React 開發必須知道的 34 個技巧文章源碼:請戳…

這五張PPT告訴你,如何打造無人駕駛“最強大腦”

“英特爾在談無人駕駛,會成為汽車制造商嗎?NO!我們要為無人駕駛提供從車、連接到云的‘最強大腦’。” 在昨天于北京舉行的英特爾無人駕駛分享會上,英特爾無人駕駛事業部中國區市場總監徐偉杰在主旨演講中開門見山。 這也是英特爾無人駕駛事業部去年11月…

javascript之ua與urlSchema

我們首先拿到瀏覽器ua: 1 var ua navigator.userAgent; 1 if (ua.indexOf("MicroMessenger") > -1) { 2 alert("微信瀏覽器"); 3 } 1 if (ua.indexOf("iPhone") > -1) { 2 alert("iphone"); 3 } 其…

ezdpl Linux自動化部署實戰

最近把ezdpl在生產環境中實施了,再加上這段時間的一些修改,一并介紹一下。再次申明: ezdpl不是開箱即用的,需要根據自己的應用環境定制。對初學者來說使用起來反倒困難更多、風險更大。它不是一個通用的項目,更多的是提…

無法打開輸入文件mysql_錯誤LNK1181,pip安裝“無法打開輸入文件”mysqlclient.lib'...

我是Python新手,正在嘗試安裝mysql模塊,但是在解決了其他5個問題之后,我現在遇到了一個問題,當我嘗試安裝該模塊時,會出現以下日志:PS C:\Users\poste> pip install mysqlCollecting mysqlUsing cached …

俄羅斯將封殺LinkedIn 推動個人數據本地化

北京時間11月11日上午消息,莫斯科一家法院本周四支持了在俄羅斯封殺職業社交網站LinkedIn的決定。 俄羅斯聯邦通信監管局(Roskomnadzor)之前要求國內外企業從2015年9月開始,必須將所有俄羅斯用戶的個人數據存儲在該國境內。Linked…

python的datetime舉例_Python datetime模塊的使用示例

1、獲取當前年月日時分秒# -*- encodingutf-8 -*-import datetimenow datetime.datetime.now()print("now:{}".format(now))year now.yearprint("year:{}".format(year))month now.monthprint("month:{}".format(month))day now.dayprint(&q…

vs2015 去除 git 源代碼 綁定,改成向tfs添加源碼管理

除了下文的方法是將源碼管理從git改成tfs之外,還要做以下幾步即可 向tfs添加源碼 打開源碼管理(管理連接),雙擊打開你要向其中添加的tfs連接選中該解決方案,右鍵 將解決方案添加到源碼管理嵌入完畢vs2015 去除 git 源代碼 綁定 第一次碰到這個…

HDU 4609 FFT

題目大意 給定n條邊的邊值,求任意取三條邊能組成三角形的概率 這里概率 P valid/tot tot (n-2)*(n-1)*n/6是沒問題的 valid表示合法的方式 先考慮,任意兩條邊組合形成方法的總數 因為邊值在100000的范圍內,這里組合用fft計算 得到最后形成和…

《日志管理與分析權威指南》一2.3 良好日志記錄的標準

本節書摘來華章計算機《日志管理與分析權威指南》一書中的第2章 ,第2.3節,(美) Anton A. Chuvakin Kevin J. Schmidt Christopher Phillips 著 姚 軍 簡于涵 劉 暉 等譯更多章節內容可以訪問云棲社區“華章計算機”公眾號查…

Python【01】【基礎部分】- A

一、WHATS PYTHON ? 1、python 簡介 Python(英語發音:/?pa?θ?n/), 是一種面向對象、解釋型計算機程序設計語言,由Guido van Rossum于1989年發明,第一個公開發行版發行于1991年。Python是純粹的自由軟件&#xff0…

java的自增自減_Java中自增和自減操作符(++/--)的那些事

自增()和自減(--)運算符在JAVA語言中存在著很多運算符,但是在實際開發中我們或許很少用到它們,在初次學習中卻時常出現它們的身影,對于這些運算符的含義和用法,是否還記得呢?1. 概述自增操作符()和自減操作符(--)是對變…

Finished yeah!

終于到了最后的博客階段,這時候才知道博客此時此刻是多么的愜意,它成了書寫心聲的自由平臺!耗時一天完成這作業說起來也是蠻辛苦的,編譯器需要新裝,IDE需要熟悉,當然最主要的是之前淺入淺出的C功底在此次作…

《Python語言程序設計》——1.6 開始學習Python

本節書摘來自華章計算機《Python語言程序設計》一書中的第1章,第1.6節,作者:[美]梁勇(Y. Daniel Liang) 更多章節內容可以訪問云棲社區“華章計算機”公眾號查看。 1.6 開始學習Python 關鍵點:…

Tomcat性能調優

1、集成apache 雖然Tomcat也可以作web服務器,但是處理靜態html的速度比不上apache,且其作為web服務器的功能遠不如Apache,因此把apache和tomcat集成起來,講html和jsp功能部分進行明確的分工,讓tomcat只處理jsp部分&…

【轉】sip中的subscribe和notify擴展應用技術

http://blog.csdn.net/hwz119/article/details/3965322轉載于:https://www.cnblogs.com/matthew-2013/p/4917207.html

再讀《被神化的框架》

開發框架,構件,組件非常地多,而且,趨勢是越來越多,特別是在java中。當然也不是說其它平臺的少。而特別是框架越來越被神化了,似乎用之解決一切問題,不用就要敲壞鍵盤。對于老衲這樣的打字員來說…

河南推出近萬億PPP投資計劃 鄭州實現智慧城市全覆蓋

1 近萬億PPP項目啟動 眼下,國內財經新聞的熱點聚焦在PPP開發上,這與PPP支撐國內經濟平衡運行的一支強勁力量正被政府看好。就連二級市場也出現了PPP概念的搶籌現象。 9月27日,股市再一次遭遇拋售,大盤創出階段性新低,然…