让我们看一个例子:在我的main.sh中,我想找一个a.sh和b.sh. 但是,a.sh可能已经采购了b.sh. 因此,它将导致b.sh中的代码执行两次.在C++中是否有类似"包含守卫"的机制?
出于某种原因,我在头文件中获得了多个内容声明,即使我正在使用标题保护.我的示例代码如下:
main.c中:
#include "thing.h"
int main(){
printf("%d", increment());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
thing.c:
#include "thing.h"
int increment(){
return something++;
}
Run Code Online (Sandbox Code Playgroud)
thing.h:
#ifndef THING_H_
#define THING_H_
#include <stdio.h>
int something = 0;
int increment();
#endif
Run Code Online (Sandbox Code Playgroud)
当我尝试编译它时,GCC说我对some变量有多个定义.ifndef应该确保不会发生这种情况,所以我很困惑为什么会这样.
所以我知道如何使用标准将包含警卫放在我自己的头文件中
#ifndef ...
#define ...
Run Code Online (Sandbox Code Playgroud)
现在,我的问题是包括不属于我自己的库.将是一个很好的例子.我有一个头文件,需要使用字符串,所以我做了以下
foo.h中
#ifndef FOO_H
#define FOO_H
#include <string>
... code etc ...
#endif
Run Code Online (Sandbox Code Playgroud)
现在,如果我有一个名为的另一个头文件..让我们说bar.h,这也需要使用<string>,我该如何防止多个包含?STL是否已经包含防护装置?
我的所有头文件都使用包括警卫和pragma一次:
#pragma once
#ifndef FILE_NAME_H
#define FILE_NAME_H
class foo
{
//foo interface..
};
#endif /* FILE_NAME_H */
Run Code Online (Sandbox Code Playgroud)
我知道pragma曾经不是标准的,并且可能在编译器中不一样,但它是否有可能导致错误?以某种方式测试它是否可用,是否会更好?
#ifdef THIS_COMPILER_SUPPORTS_PRAGMA_ONCE
#pragma once
#endif
#ifndef FILE_NAME_H
#define FILE_NAME_H
class foo
{
//foo interface..
};
#endif /* FILE_NAME_H */
Run Code Online (Sandbox Code Playgroud)
我想提供一次pragma作为可能加速编译和避免名称冲突的选项,同时仍然提供编译器之间的兼容性.
我习惯在我的对象周围放置标题守卫,如:
#ifndef SOMETHING_H
#define SOMETHING_H
class Something {
...
}
#endif
Run Code Online (Sandbox Code Playgroud)
但我也得到了他们也做的代码:
#ifndef SOMETHING_H
#include "something.h"
#endif
Run Code Online (Sandbox Code Playgroud)
对于每个包括.据说,这更好.为什么?围绕物体的守卫是多余的吗?
我一直在玩gcc的-H选项,它打印出有关C和C ++编译中直接和间接包含的信息(gcc手册的相关部分)。
作为输出的一部分,有一个部分“多个包含保护可能对:有用”,其中列出了许多项目和系统头。
这是什么意思,如何确定此列表,以及为什么说“多个”包含防护可能有用?
(我熟悉包含防护的一般概念,以及为什么要使用它们-我正在寻找有关此消息的详细信息,以及这对我的项目意味着什么。)
请不要介意以下最小例子的陌生感(我必须把它做得更大才能证明我为什么这样做):
文件test.cpp:
#include "a.h"
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
档案啊:
namespace N { // without namespace all is well!
#include "b.h"
}
Run Code Online (Sandbox Code Playgroud)
文件bh:
/// \file
#ifndef GUARD
#define GUARD
struct A {};
#define CMD 5 // without this, all is well!
#endif
Run Code Online (Sandbox Code Playgroud)
Doxygen 1.8.11抱怨:
warning: Member GUARD (macro definition) of file a.h is not documented.
Run Code Online (Sandbox Code Playgroud)
第一个有趣的事情是警告提到a.h.第二个是如果删除了任何一条注释行,警告就会消失.这里发生了什么?
我在某处读到(抱歉,再也找不到链接了)在标题的第一行应该始终是 #include 保护,因为编译器可以在不打开头文件的情况下看到它。因此,如果头文件已经包含在内,它不会打开文件只是为了再次关闭它,这会加快构建过程。
但是我总是在每个文件的开头都有一个注释块。所以我的问题是,#include 守卫应该写在注释块之前还是之后?
这种风格更好吗:
///////////////////////
// Name: code.h
// Author: Me
// Date: dd.mm.yyyy
// Description: This code executes a specific task
///////////////////////
#ifndef CODE_H_
#define CODE_H_
...
#endif
Run Code Online (Sandbox Code Playgroud)
或者这种风格更好:
#ifndef CODE_H_
#define CODE_H_
///////////////////////
// Name: code.h
// Author: Me
// Date: dd.mm.yyyy
// Description: This code executes a specific task
///////////////////////
...
#endif
Run Code Online (Sandbox Code Playgroud)
或者根本就没有关系?
我在C ++项目上使用Doxygen 1.8.13。
通常,我希望Doxygen记录我的宏。但是,我显然不希望它记录我的头文件包括卫兵:
#ifndef FOO_H_
#define FOO_H_
... etc ...
#endif // FOO_H
Run Code Online (Sandbox Code Playgroud)
...但是Doxygen默认情况下会为其添加一个文档条目。我知道我可以通过以下方法解决此问题:
///@cond
#ifndef FOO_H_
#define FOO_H_
///@endcond
... etc ...
#endif // FOO_H
Run Code Online (Sandbox Code Playgroud)
但是我不想在每个头文件中添加两条无用的行!有什么我可以做的吗?
doxygen.cfg 内容:
#ifndef FOO_H_
#define FOO_H_
... etc ...
#endif // FOO_H
Run Code Online (Sandbox Code Playgroud) 我在一个项目(Visual Studio)中有3个*.c文件(file1.c,file2.c和file3.c)和1个*.h文件(file3.h).
/*******************************
file3.h
********************************/
#ifndef FILE3_H
#define FILE3_H
int gintVariable = 400;
#endif
Run Code Online (Sandbox Code Playgroud)
/*******************************
file1.c
********************************/
#include "file3.h"
#include <stdio.h>
#include <conio.h>
int modifyGlobalVariable(void);
void printGlobalVariable(void);
int main(void)
{
modifyGlobalVariable();
printGlobalVariable();
printf("Global variable: %d\n", gintVariable++);
getch();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
/*******************************
file2.c
********************************/
#include "file3.h"
int modifyGlobalVariable(void)
{
return gintVariable++;
}
Run Code Online (Sandbox Code Playgroud)
/*******************************
file3.c
********************************/
#include "file3.h"
#include <stdio.h>
void printGlobalVariable(void)
{
printf("Global: %d\n", gintVariable++);
}
Run Code Online (Sandbox Code Playgroud)
当我在VS中构建解决方案时,它会给出错误"_gintVariable already …
include-guards ×10
c++ ×6
c ×2
doxygen ×2
header-files ×2
compilation ×1
gcc ×1
header ×1
performance ×1
pragma ×1
shell ×1
stl ×1