欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

有關(guān)C++頭文件的包含順序研究

 更新時(shí)間:2017年01月08日 07:50:36   投稿:jingxian  
下面小編就為大家?guī)硪黄嘘P(guān)C++頭文件的包含順序研究。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

一.《Google C++ 編程風(fēng)格指南》里的觀點(diǎn)

公司在推行編碼規(guī)范,領(lǐng)導(dǎo)提議基本上使用《Google C++ 編程風(fēng)格指南》。

其中《Google C++ 編程風(fēng)格指南》對于頭文件的包含順序是這樣的:
 
Names and Order of Includes
link ▽Use standard order for readability and to avoid hidden dependencies:C library, C++ library, other libraries' .h, your project's .h.
All of a project's header files should belisted as descendants of the project's source directory without use of UNIXdirectory shortcuts . (the current directory) or .. (the parent directory). Forexample, google-awesome-project/src/base/logging.h should be included as
 
#include "base/logging.h"
In dir/foo.cc or dir/foo_test.cc, whosemain purpose is to implement or test the stuff in dir2/foo2.h, order yourincludes as follows:
 
dir2/foo2.h (preferred location — seedetails below).
C system files.
C++ system files.
Other libraries' .h files.
Your project's .h files.
The preferred ordering reduces hiddendependencies. We want every header file to be compilable on its own. Theeasiest way to achieve this is to make sure that every one of them is the first.h file #included in some .cc.
 
dir/foo.cc and dir2/foo2.h are often in thesame directory (e.g. base/basictypes_test.cc and base/basictypes.h), but can bein different directories too.
 
Within each section it is nice to order theincludes alphabetically.
 
For example, the includes ingoogle-awesome-project/src/foo/internal/fooserver.cc might look like this:

<span style="font-size:16px;"> 
#include "foo/public/fooserver.h" // Preferred location. 
 
#include <sys/types.h> 
 
#include <unistd.h> 
 
  
 
#include <hash_map> 
 
#include <vector> 
 
  
 
#include "base/basictypes.h" 
 
#include"base/commandlineflags.h" 
 
#include "foo/public/bar.h" 
 
 </span> 

在這里我談一下我對上面的理解(如不當(dāng),還請諸位同學(xué)指正):

1. 為了加強(qiáng)可讀性和避免隱含依賴,應(yīng)使用下面的順序:C標(biāo)準(zhǔn)庫、C++標(biāo)準(zhǔn)庫、其它庫的頭文件、你自己工程的頭文件。不過這里最先包含的是首選的頭文件,即例如a.cpp文件中應(yīng)該優(yōu)先包含a.h。首選的頭文件是為了減少隱藏依賴,同時(shí)確保頭文件和實(shí)現(xiàn)文件是匹配的。具體的例子是:假如你有一個(gè)cc文件(Linux平臺的cpp文件后綴為cc)是google-awesome-project/src/foo/internal/fooserver.cc,那么它所包含的頭文件的順序如下:

<span style="font-size:16px;">#include "foo/public/fooserver.h" // Preferred location. 
 
#include <sys/types.h> 
#include <unistd.h> 
 
#include <hash_map> 
#include <vector> 
 
#include "base/basictypes.h" 
#include "base/commandlineflags.h" 
#include "foo/public/bar.h" 
 
</span> 

2. 在包含頭文件時(shí)應(yīng)該加上頭文件所在工程的文件夾名,即假如你有這樣一個(gè)工程base,里面有一個(gè)logging.h,那么外部包含這個(gè)頭文件應(yīng)該這樣寫:

#include "base/logging.h",而不是#include "logging.h"
 
我們看到的是這里《Google C++ 編程風(fēng)格指南》倡導(dǎo)的原則背后隱藏的目的是:

1. 為了減少隱藏依賴,同時(shí)頭文件和其實(shí)現(xiàn)文件匹配,應(yīng)該先包含其首選項(xiàng)(即其對應(yīng)的頭文件)。
 
2. 除了首選項(xiàng)外,遵循的是從一般到特殊的原則。不過我覺得《Google C++ 編程風(fēng)格指南》的順序:C標(biāo)準(zhǔn)庫、C++標(biāo)準(zhǔn)庫、其它庫的頭文件、你自己工程的頭文件中漏了最前面的一項(xiàng):操作系統(tǒng)級別的頭文件,比如上面的例子sys/types.h估計(jì)不能歸入C標(biāo)準(zhǔn)庫,而是Linux操作系統(tǒng)提供的SDK吧。因此我覺得更準(zhǔn)確的說法應(yīng)該是:OS SDK .h , C標(biāo)準(zhǔn)庫、C++標(biāo)準(zhǔn)庫、其它庫的頭文件、你自己工程的頭文件。
 
3.之所以要將頭文件所在的工程目錄列出,作用應(yīng)該是命名空間是一樣的,就是為了區(qū)分不小心造成的文件重名。
 
二.《C++編程思想》中的不同觀點(diǎn)
  
與《Google C++ 編程風(fēng)格指南》不同的是,《C++編程思想》倡導(dǎo)一種不同的規(guī)則。《C++編程思想》P432提到:

頭文件被包含的順序是從“最特殊到最一般”。這就是,在本地目錄的任何頭文件首先被包含。然后是我們自己的所有“工具”頭文件,隨后是第三方庫頭文件,接著是標(biāo)準(zhǔn)C++庫頭文件和C庫頭文件。

要了解其原因:可以看JohnLakos在《Large ScaleC++ Softwre Design》(注:其中文譯名為《大規(guī)模C++程序設(shè)計(jì)》)中的一段話:
 
保證.h文件的組成部分不被它自身解析(parse),這可以避免潛在的使用錯(cuò)誤。因?yàn)楸蛔陨斫馕鋈狈γ鞔_提供的聲明或定義。在.c文件的第一行包含.h 文件能確保所有對于構(gòu)件的物理界面重要的內(nèi)部信息塊都在.h中(如果的確是缺少了某些信息塊,一旦編譯這個(gè).c文件時(shí)就可以發(fā)現(xiàn)這個(gè)問題)。
 
如果包含頭文件的順序是“從最特殊到最一般”,如果我們的頭文件不被它自己解析。我們將馬上找到它,防止麻煩事情發(fā)生。
 
三.我的試驗(yàn)
 
到底哪一種包含順序好呢?我使用VS 2005編一個(gè)控制臺測試工程TestInc,里面有幾個(gè)文件。
 
MyMath.h的代碼如下:

<span style="font-size:16px;">#pragma once 
 
#pragma once 
double acos(double Num); 
</span> 

MyMath.cpp的代碼如下:

<span style="font-size:16px;">double acos(double Num) 
{ 
  return 1.0; 
} 
 
</span> 

TestInc.cpp的代碼如下:

<span style="font-size:16px;">#include "stdafx.h" 
#include "TestInc.h" 
#include <stdio.h> 
#include <math.h> 
 
 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
  double a = acos(0.5); 
  return 0; 
} 
</span> 

結(jié)果出現(xiàn)錯(cuò)誤:

1>c:\program files\microsoft visualstudio 8\vc\include\math.h(107) : error C2732: 鏈接規(guī)范與“acos”的早期規(guī)范沖突
1>       c:\program files\microsoft visual studio 8\vc\include\math.h(107) : 參見“acos”的聲明
 
然后我把TestInc.cpp的頭文件包含順序改為:

<span style="font-size:16px;">#include "stdafx.h" 
#include <stdio.h> 
#include <math.h> 
#include "TestInc.h" 
</span> 

則編譯通過了。在調(diào)試運(yùn)行時(shí)main函數(shù)調(diào)用還是C標(biāo)準(zhǔn)庫的函數(shù)acos,看來函數(shù)調(diào)用的順序是按頭文件的包含順序來的,即我自定義的acos函數(shù)被覆蓋了(如果TestInc.h里包含了內(nèi)聯(lián)函數(shù),則優(yōu)先調(diào)用的是內(nèi)聯(lián)函數(shù))。
 
從這個(gè)小實(shí)驗(yàn)中我得出如下結(jié)論:《Google C++ 編程風(fēng)格指南》和《C++編程思想》倡導(dǎo)的包含頭文件的順序各有優(yōu)點(diǎn),《Google C++ 編程風(fēng)格指南》應(yīng)該能大量減少隱藏的頭文件依賴,而《C++編程思想》則很容易讓你清楚知道你所定義的接口是否和系統(tǒng)庫及第三方庫發(fā)生沖突。
 
四.頭文件包含中的預(yù)編譯功能
 
在Visual Studio環(huán)境下開發(fā)我們發(fā)現(xiàn)幾乎每個(gè)cpp文件都要包含stdafx.h這個(gè)文件,而且要把它放在最前面的位置,否則就會(huì)出錯(cuò)。這是為什么呢?
      
原來Visual Studio采用一種預(yù)編譯的機(jī)制。要了解預(yù)編譯機(jī)制,先介紹一下預(yù)編譯頭。所謂的預(yù)編譯頭就是把一個(gè)工程中的那一部分代碼,預(yù)先編譯好放在一個(gè)文件里(通常是以.pch為擴(kuò)展名的),這個(gè)文件就稱為預(yù)編譯頭文件這些預(yù)先編譯好的代碼可以是任何的C/C++代碼,甚至是inline的函數(shù),但是必須是穩(wěn)定的,在工程開發(fā)的過程中不會(huì)被經(jīng)常改變。如果這些代碼被修改,則需要重新編譯生成預(yù)編譯頭文件。注意生成預(yù)編譯頭文件是很耗時(shí)間的。同時(shí)你得注意預(yù)編譯頭文件通常很大,通常有6- 7M大。注意及時(shí)清理那些沒有用的預(yù)編譯頭文件。
 
也許你會(huì)問:現(xiàn)在的編譯器都有Time stamp的功能,編譯器在編譯整個(gè)工程的時(shí)候,它只會(huì)編譯那些經(jīng)過修改的文件,而不會(huì)去編譯那些從上次編譯過,到現(xiàn)在沒有被修改過的文件。那么為什么還要預(yù)編譯頭文件呢?答案在這里,我們知道編譯器是以文件為單位編譯的,一個(gè)文件經(jīng)過修改后,會(huì)重新編譯整個(gè)文件,當(dāng)然在這個(gè)文件里包含的所有頭文件中的東西(.eg Macro, Preprocessor )都要重新處理一遍。 VC的預(yù)編譯頭文件保存的正是這部分信息。以避免每次都要重新處理這些頭文件。
 
根據(jù)上文介紹,預(yù)編譯頭文件的作用當(dāng)然就是提高便宜速度了,有了它你沒有必要每次都編譯那些不需要經(jīng)常改變的代碼。編譯性能當(dāng)然就提高了。
 
要使用預(yù)編譯頭,我們必須指定一個(gè)頭文件,這個(gè)頭文件包含我們不會(huì)經(jīng)常改變的代碼和其他的頭文件,然后我們用這個(gè)頭文件來生成一個(gè)預(yù)編譯頭文件(.pch 文件)想必大家都知道StdAfx.h這個(gè)文件。很多人都認(rèn)為這是VC提供的一個(gè)“系統(tǒng)級別”的,編譯器帶的一個(gè)頭文件。其實(shí)不是的,這個(gè)文件可以是任何名字的。我們來考察一個(gè)典型的由AppWizard生成的MFC Dialog Based 程序的預(yù)編譯頭文件。(因?yàn)锳ppWizard會(huì)為我們指定好如何使用預(yù)編譯頭文件,默認(rèn)的是StdAfx.h,這是VC起的名字)。我們會(huì)發(fā)現(xiàn)這個(gè)頭文件里包含了以下的頭文件:

<span style="font-size:16px;">#include <afxwin.h> // MFC core and standard components 
#include <afxext.h> // MFC extensions 
#include <afxdisp.h> // MFC Automation classes 
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls 
#include <afxcmn.h> 
</span> 

這些正是使用MFC的必須包含的頭文件,當(dāng)然我們不太可能在我們的工程中修改這些頭文件的,所以說他們是穩(wěn)定的。
 
那么我們?nèi)绾沃付ㄋ鼇砩深A(yù)編譯頭文件。我們知道一個(gè)頭文件是不能編譯的。所以我們還需要一個(gè)cpp文件來生成.pch 文件。這個(gè)文件默認(rèn)的就是StdAfx.cpp。在這個(gè)文件里只有一句代碼就是:#include“Stdafx.h”。原因是理所當(dāng)然的,我們僅僅是要它能夠編譯而已―――也就是說,要的只是它的.cpp的擴(kuò)展名。我們可以用/Yc編譯開關(guān)來指定StdAfx.cpp來生成一個(gè).pch文件,通過/Fp 編譯開關(guān)來指定生成的pch文件的名字。打開project ->Setting->C/C++ 對話框。把Category指向Precompiled Header。在左邊的樹形視圖里選擇整個(gè)工程,Project Options(右下角的那個(gè)白的地方)可以看到 /Fp “debug/PCH.pch”,這就是指定生成的.pch文件的名字,默認(rèn)的通常是 <工程名>.pch。然后,在左邊的樹形視圖里選擇 StdAfx.cpp,這時(shí)原來的Project Option變成了 Source File Option(原來是工程,現(xiàn)在是一個(gè)文件,當(dāng)然變了)。在這里我們可以看到 /Yc開關(guān),/Yc的作用就是指定這個(gè)文件來創(chuàng)建一個(gè)Pch文件。/Yc后面的文件名是那個(gè)包含了穩(wěn)定代碼的頭文件,一個(gè)工程里只能有一個(gè)文件的可以有 YC開關(guān)。VC就根據(jù)這個(gè)選項(xiàng)把 StdAfx.cpp編譯成一個(gè)Obj文件和一個(gè)PCH文件。

這樣,我們就設(shè)置好了預(yù)編譯頭文件。也就是說,我們可以使用預(yù)編譯頭功能了。

以下是注意事項(xiàng):
 
1)如果使用了/Yu,就是說使用了預(yù)編譯,我們在每個(gè).cpp文件的最開頭,包含你指定產(chǎn)生pch文件的.h文件(默認(rèn)是stdafx.h)不然就會(huì)有問題。如果你沒有包含這個(gè)文件,就告訴你Unexpected file end.
 
2)如果你把pch文件不小心丟了,根據(jù)以上的分析,你只要讓編譯器生成一個(gè)pch文件就可以了。也就是說把stdafx.cpp(即指定/Yc的那個(gè)cpp文件)重新編譯一遍就可以了。   

那么在Linux平臺下有沒有這種預(yù)編譯機(jī)制呢?如果有,它是怎么實(shí)現(xiàn)的呢?Linux平臺下GCC編譯器也實(shí)現(xiàn)了預(yù)編譯機(jī)制的。這里以開源IDE CodeBlocks(CodeBlocks內(nèi)置了GCC編譯器)的工程為例來說明Linux平臺的實(shí)現(xiàn):
 
使用CodeBlocks建一個(gè)C++工程,然后新建一個(gè)my_pch.h,輸入如下代碼:

<span style="font-size:16px;">/*************************************************************** 
 * Name:   my_pch.h 
 * Purpose:  Header to create Pre-Compiled Header (PCH) 
 * Author:   () 

 * Copyright: () 
 * License: 
 * 使用方法: 項(xiàng)目構(gòu)建選項(xiàng)-->其他選項(xiàng)-->填入下面兩行 
 -Winvalid-pch 
 -include my_pch.h 
 **************************************************************/ 
 
#ifndef MY_PCH_H_INCLUDED 
#define MY_PCH_H_INCLUDED 
 
// put here all your rarely-changing header files 
 
#include <iostream> 
#include <string> 
 
#endif 
</span> 

然后在項(xiàng)目構(gòu)建選項(xiàng)-->其他選項(xiàng)-->填入下面兩行

 -Winvalid-pch
 -include my_pch.h

就可以啟用預(yù)編譯文件頭。
然后 main.cpp 就可以不用 include 頭文件了,直接這樣就可以編譯了,

<span style="font-size:16px;">int main() 
{  
using namespace std; 
  cout << "Hello world!" << endl; 
  return 0; 
} 
</span> 

即使在上面的代碼寫上下面一行,其實(shí)是不起作用的:

<span style="font-size:16px;">#include <iostream> </span> 

以上就是小編為大家?guī)淼挠嘘P(guān)C++頭文件的包含順序研究全部內(nèi)容了,希望大家多多支持腳本之家~

相關(guān)文章

  • C++實(shí)現(xiàn)五子棋游戲

    C++實(shí)現(xiàn)五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C語言?指針數(shù)組進(jìn)階詳解

    C語言?指針數(shù)組進(jìn)階詳解

    在C語言和C++等語言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-02-02
  • C語言獲取Linux系統(tǒng)精確時(shí)間的方法

    C語言獲取Linux系統(tǒng)精確時(shí)間的方法

    下面小編就為大家?guī)硪黄狢語言獲取Linux系統(tǒng)精確時(shí)間的方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • C++編程語言中賦值運(yùn)算符重載函數(shù)(operator=)的使用

    C++編程語言中賦值運(yùn)算符重載函數(shù)(operator=)的使用

    本文主要介紹了C++編程語言中賦值運(yùn)算符重載函數(shù)(operator=)介紹,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • 關(guān)于define與C 的內(nèi)存

    關(guān)于define與C 的內(nèi)存

    本文主要介紹了C語言中#define到底存在程序的哪個(gè)區(qū),以及工作流程和效率與普通函數(shù)的區(qū)別,希望能幫助需要的小伙伴
    2016-07-07
  • C++超詳細(xì)講解標(biāo)準(zhǔn)庫

    C++超詳細(xì)講解標(biāo)準(zhǔn)庫

    C++強(qiáng)大的功能來源于其豐富的類庫及庫函數(shù)資源。C++標(biāo)準(zhǔn)庫(C++ Standard Library, 亦可稱作,C++標(biāo)準(zhǔn)程序庫)的內(nèi)容總共在50個(gè)標(biāo)準(zhǔn)頭文件中定義。在C++開發(fā)中,要盡可能地利用標(biāo)準(zhǔn)庫完成
    2022-06-06
  • 掌握C++編程中反斜杠續(xù)行符的使用方法

    掌握C++編程中反斜杠續(xù)行符的使用方法

    這篇文章主要介紹了掌握C++編程中反斜杠續(xù)行符的使用方法,包括取反斜杠的本意的方法等基本知識點(diǎn),需要的朋友可以參考下
    2016-01-01
  • 詳解C語言位域的使用與注意事項(xiàng)

    詳解C語言位域的使用與注意事項(xiàng)

    所謂“位域”是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾個(gè)不同的區(qū)域, 并說明每個(gè)區(qū)域的位數(shù)。每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。 這樣就可以把幾個(gè)不同的對象用一個(gè)字節(jié)的二進(jìn)制位域來表示。下面這篇文章就給大家介紹下關(guān)于C語言中位域的使用與注意事項(xiàng)。
    2016-12-12
  • C語言實(shí)現(xiàn)大數(shù)值金額大寫轉(zhuǎn)換的方法詳解

    C語言實(shí)現(xiàn)大數(shù)值金額大寫轉(zhuǎn)換的方法詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用C語言實(shí)現(xiàn)大數(shù)值金額大寫轉(zhuǎn)換的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-03-03
  • C++初階學(xué)習(xí)之模板進(jìn)階

    C++初階學(xué)習(xí)之模板進(jìn)階

    這篇文章主要為大家介紹了C++模板進(jìn)階,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01

最新評論