公司在履行编码范例,指导发起基本上运用《Google C++ 编程作风指南》。个中《Google C++ 编程作风指南》关于头文件的包括递次是如许的:
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: #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"
在这里我谈一下我对上面的明白(如不当,还请诸位同砚斧正):
1. 为了增强可读性和防备隐含依靠,应运用下面的递次:C规范库、C++规范库、别的库的头文件、你本身工程的头文件。不过这里最早包括的是首选的头文件,即比方a.cpp文件中应当优先包括a.h。首选的头文件是为了削减隐蔽依靠,同时确保头文件和完成文件是婚配的。详细的例子是:假如你有一个cc文件(linux平台的cpp文件后缀为cc)是google-awesome-project/src/foo/internal/fooserver.cc,那末它所包括的头文件的递次以下:
#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"
2. 在包括头文件时应当加上头文件地点工程的文件夹名,即假如你有如许一个工程base,内里有一个logging.h,那末外部包括这个头文件应当如许写:
#include “base/logging.h”,而不是#include “logging.h”
我们看到的是这里《Google C++ 编程作风指南》提倡的准绳背地隐蔽的目标是:
1. 为了削减隐蔽依靠,同时头文件和其完成文件婚配,应当先包括其首选项(即其对应的头文件)。
2. 除了首选项外,遵照的是从平常到特别的准绳。不过我以为《Google C++ 编程作风指南》的递次:C规范库、C++规范库、别的库的头文件、你本身工程的头文件中漏了最前面的一项:操作体系级别的头文件,比方上面的例子sys/types.h预计不能归入C规范库,而是Linux操作体系供应的SDK吧。因而我以为更正确的说法应当是:OS SDK .h , C规范库、C++规范库、别的库的头文件、你本身工程的头文件。
3.之所以要将头文件地点的工程目次列出,作用应当是定名空间是一样的,就是为了辨别不小心形成的文件重名。
二.《C++编程头脑》中的差别看法
与《Google C++ 编程作风指南》差别的是,《C++编程头脑》提倡一种差别的划定规矩。《C++编程头脑》P432提到:
头文件被包括的递次是从“最特别到最平常”。这就是,在当地目次的任何头文件起首被包括。然后是我们本身的一切“东西”头文件,随后是第三方库头文件,接着是规范C++库头文件和C库头文件。
要相识其缘由:可以看JohnLakos在《Large ScaleC++ Softwre Design》(注:个中文译名为《大规模C++顺序设计》)中的一段话:
保证.h文件的组成部份不被它本身剖析(parse),这可以防备潜伏的运用毛病。由于被本身剖析缺少明白供应的声明或定义。在.c文件的第一行包括.h 文件能确保一切关于构件的物理界面主要的内部信息块都在.h中(假如的确是缺少了某些信息块,一旦编译这个.c文件时就可以发明这个题目)。
假如包括头文件的递次是“从最特别到最平常”,假如我们的头文件不被它本身剖析。我们将立时找到它,防备贫苦事变发作。
三.我的试验
究竟哪种包括递次好呢?我运用VS 2005编一个控制台测试工程TestInc,内里有几个文件。
MyMath.h的代码以下:
#pragma once double acos(double Num); MyMath.cpp的代码以下: double acos(double Num) { return 1.0; }
TestInc.cpp的代码以下:
#include "TestInc.h" #include <stdio.h> #include <math.h> int _tmain(int argc, _TCHAR* argv[]) { double a = acos(0.5); return 0; }
效果涌现毛病:
1>c:program filesmicrosoft visualstudio 8vcincludemath.h(107) : error C2732: 链接范例与“acos”的初期范例争执 1> c:program filesmicrosoft visual studio 8vcincludemath.h(107) : 拜见“acos”的声明
然后我把TestInc.cpp的头文件包括递次改成:
#include <stdio.h> #include <math.h> #include "TestInc.h"
则编译经由过程了。在调试运行时main函数挪用照样C规范库的函数acos,看来函数挪用的递次是按头文件的包括递次来的,即我自定义的acos函数被覆盖了(假如TestInc.h里包括了内联函数,则优先挪用的是内联函数)。
从这个小试验中我得出以下结论:《Google C++ 编程作风指南》和《C++编程头脑》提倡的包括头文件的递次各有长处,《Google C++ 编程作风指南》应当能大批削减隐蔽的头文件依靠,而《C++编程头脑》则很轻易让你清晰晓得你所定义的接口是不是和体系库及第三方库发作争执。
四.头文件包括中的预编译功用
在Visual Studio环境下开辟我们发明险些每一个cpp文件都要包括stdafx.h这个文件,而且要把它放在最前面的位置,不然就会失足。这是为何呢?
本来Visual Studio采纳一种预编译的机制。要相识预编译机制,先引见一下预编译头。所谓的预编译头就是把一个工程中的那一部份代码,预先编译好放在一个文件里(一般是以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C++代码,以至是inline的函数,然则必需是稳固的,在工程开辟的过程当中不会被常常转变。假如这些代码被修正,则须要从新编译生成预编译头文件。注重生成预编译头文件是很耗时间的。同时你得注重预编译头文件一般很大,一般有6- 7M大。注重实时清算那些没有用的预编译头文件。
或许你会问:如今的编译器都有Time stamp的功用,编译器在编译全部工程的时刻,它只会编译那些经由修正的文件,而不会去编译那些从上次编译过,到如今没有被修正过的文件。那末为何还要预编译头文件呢?答案在这里,我们晓得编译器是以文件为单元编译的,一个文件经由修正后,会从新编译全部文件,固然在这个文件里包括的一切头文件中的东西(.eg Macro, Preprocessor )都要从新处理一遍。 VC的预编译头文件保留的恰是这部份信息。以防备每次都要从新处理这些头文件。
依据上文引见,预编译头文件的作用固然就是进步廉价速度了,有了它你没有必要每次都编译那些不须要常常转变的代码。编译机能固然就进步了。
要运用预编译头,我们必需指定一个头文件,这个头文件包括我们不会常常转变的代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch 文件)想必人人都晓得StdAfx.h这个文件。很多人都以为这是VC供应的一个“体系级别”的,编译器带的一个头文件。实在不是的,这个文件可以是任何名字的。我们来考核一个典范的由AppWizard生成的MFC Dialog Based 顺序的预编译头文件。(由于AppWizard会为我们指定好怎样运用预编译头文件,默许的是StdAfx.h,这是VC起的名字)。我们会发明这个头文件里包括了以下的头文件:
#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>
这些恰是运用MFC的必需包括的头文件,固然我们不太可能在我们的工程中修正这些头文件的,所以说他们是稳固的。
那末我们怎样指定它来生成预编译头文件。我们晓得一个头文件是不能编译的。所以我们还须要一个cpp文件来生成.pch 文件。这个文件默许的就是StdAfx.cpp。在这个文件里只要一句代码就是:#include“Stdafx.h”。缘由是天经地义的,我们仅仅是要它可以编译罢了―――也就是说,要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指定StdAfx.cpp来生成一个.pch文件,经由过程/Fp 编译开关来指定生成的pch文件的名字。翻开project ->Setting->C/C++ 对话框。把Category指向Precompiled Header。在左侧的树形视图里挑选全部工程,Project Options(右下角的谁人白的处所)可以看到 /Fp “debug/PCH.pch”,这就是指定生成的.pch文件的名字,默许的一般是 .pch。然后,在左侧的树形视图里挑选 StdAfx.cpp,这时候本来的Project Option变成了 Source File Option(本来是工程,如今是一个文件,固然变了)。在这里我们可以看到 /Yc开关,/Yc的作用就是指定这个文件来建立一个Pch文件。/Yc背面的文件名是谁人包括了稳固代码的头文件,一个工程里只能有一个文件的可以有 YC开关。VC就依据这个选项把 StdAfx.cpp编译成一个Obj文件和一个PCH文件。
如许,我们就设置好了预编译头文件。也就是说,我们可以运用预编译头功用了。以下是注重事项:
1)假如运用了/Yu,就是说运用了预编译,我们在每一个.cpp文件的最开首,包括你指定发生pch文件的.h文件(默许是stdafx.h)不然就会有题目。假如你没有包括这个文件,就通知你Unexpected file end.
2)假如你把pch文件不小心丢了,依据以上的剖析,你只要让编译器生成一个pch文件就可以了。也就是说把stdafx.cpp(即指定/Yc的谁人cpp文件)从新编译一遍就可以了。
那末在Linux平台下有没有这类预编译机制呢?假如有,它是怎样完成的呢?Linux平台下GCC编译器也完成了预编译机制的。这里以开源IDE CodeBlocks(CodeBlocks内置了GCC编译器)的工程为例来申明Linux平台的完成:
运用CodeBlocks建一个C++工程,然后新建一个my_pch.h,输入以下代码:
/*************************************************************** * Name: my_pch.h * Purpose: Header to create Pre-Compiled Header (PCH) * Author: () * Created: 2010-10-26 * Copyright: () * License: * 运用方法: 项目构建选项-->其他选项-->填入下面两行 -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
然后在项目构建选项–>其他选项–>填入下面两行
-Winvalid-pch -include my_pch.h
就可以启用预编译文件头。
然后 main.cpp 就可以不必 include 头文件了,直接如许就可以编译了
int main() { using namespace std; cout << "Hello world!" << endl; return 0; }
纵然在上面的代码写上下面一行,实际上是不起作用的:
#include <iostream>
以上就是C++ 头文件的包括递次研讨的内容,更多相关内容请关注ki4网(www.ki4.cn)!