前几天看到同一个项目中有的地方使用了#ifndef...#define ...#endif,而有的地方却用了#pragma once,于是我就纠结了,这两者有神马区别呢?今天仔细查了一下,发现还是有一点点的区别,不过不大,简单记录一下。
一.简介
#ifndef ...#define ...#endif和#pragma once都是为了解决同一个问题的,就是防止头文件被重复包含和编译。这种宏定义都是作用于编译阶段,属于条件编译,控制编译流,可以让我们按照想要的方式来编译我们的代码。
二.#ifndef ...#define ...#endif
这个方法是最早期的使用方法,其实就是字面的理解,ifndef 是if not define的缩写,就是如果没有包含这个文件,那么包含这个文件,而如果包含了这个文件,那么在编译的时候,宏定义的条件不成立,就会跳过这个#define和#endif之间的内容。达到防止重复包含的作用。
//includetest头文件
#ifndef __INCLUDETEST_H_
#define __INCLUDETEST_H_
void TestFunc();
#endif
这样,如果有两个文件,都包含了TestFunc头文件,第一个如果被包含了,那么在下一次遇到#ifndef __INCLUDETEST_H_时,这个条件为假,下面的就不会再包含。
优点如下:
1.原生支持,适合跨平台。这种方法是语言本身支持的,在所有C++编译器上都可以支持。所以,如果是跨平台方式,最好使用这种方式,比较保险。
2.可以保证内容相同的而名字不同的文件不被包含,虽然这种情况比较少,但是还是有可能的。即两个文件虽然名字不同,但是内容完全相同,这时候,就通过#ifndef区别出来,保证这种情况不会被重复编译。
缺点如下:
1.比较麻烦...好大一串,而且,这个#ifndef ...后面的宏名字还需要自己定义,一般就是文件名的大写。
2.自己定义#ifndef后面的宏名字,虽然可以保证内容相同的文件不被重复包含,但是,如果两个文件的宏名字相同了,就有可能导致一个文件被包含了,另一个不被包含,进而导致明明声明了函数,却找不到的情况。
三.#pragma once
这个倒是灰常精简,就一句话。这种是由编译器提供编译的保证。只需要在头文件头添加这句话,就可以保证这个文件不被重复包含了。
//includetest头文件:
#pragma once
void TestFunc();
优点如下:
1.简单粗暴,一句搞定。而且不需要上面那种情况,需要绞尽脑汁的想一个尽可能长长的宏名字。
2.不用自己起宏名字,就可以避免上面那种可能有宏名字冲突的情况。
缺点如下:
1.这个是微软发明的东东,所以不是普适性的。有些老的编译器还不支持这条特性,虽然现在这条已经基本被各种编译器支持了,不过,保险的话,跨平台的还是用上一种。
2.不能保证内容相同但名字不同的文件被重复包含。
其实,这两者的优缺点是互补的,我们可以视情况而定,到底用哪一种。最好是使用同一种。本人以前还干过两个一起用的蠢事....