c – 为什么要将整个标题内容放在保护令牌中?
作者:互联网
C和C区分声明和定义.
您可以多次声明符号,但只允许您定义一次.通过学习这一点,我有一个想法,将声明放在守卫之外,而守卫内部的定义:
// declarations
int foo(int x, int y);
int bar(int x, int y);
extern double something;
class X;
#ifndef _MY_HEADER_H_
#define _MY_HEADER_H_
#include "otherheader1.h"
#include "otherheader2.h"
// definitions of structures, classes.
class X
{
// blah blah...
};
#endif
通过这种方式,我可以按照我想要的顺序包含我的标题.并且可能循环依赖不会成为问题.
那么,如果我们可以将声明放在外面,为什么要使用警卫令牌来保护整个标头呢?
我的理由如下:
当两个标题以某种方式相互引用时,您可能经常遇到问题.您通常会收到未声明的符号错误,而您的第一反应是包含必要的标题.但是当你的两个标题碰巧包含在一起时,你就会得到神秘的错误.
啊:
#ifndef A_H
#define A_H
#include "b.h"
class A {B *b;}
#endif
b.h
#ifndef B_H
#define B_H
#include "a.h"
class B {A *a;}
#endif
当你在b.cpp中包含b.h时,你会在a.h中得到一个错误,即B未声明,但包含了标题. (这是一个重量级的时刻.)
这是因为标头守卫不会嵌套:
#ifndef B_H
#define B_H
#ifndef A_H
#define A_H
// B_H already defined no include here.
class A {B *b;}
#endif
class B {A *a;}
#endif
如果你把声明放在守卫之外,你可以阻止这个:
class B; // in b.h
#ifndef B_H
#define B_H
class A; // in a.h
#ifndef A_H
#define A_H
class B; // again from b.h
// B_H already defined no include here, no redefinition.
class A {B *b;}
#endif
class B {A *a;}
#endif
这里没问题.
更新:将标题包含在警卫中(对不起,这是一个错误).
解决方法:
当你只考虑“声明”时,你错过了一半的故事. C也有一个“类定义”的概念,它是第三种新型动物 – 它既是(类的)定义,也是成员函数的声明.
由于类可能不会被定义多次(就像任何定义一样),因此不能包含带有类定义的头文件多次.
现在假设你在foo.hpp中有一些实用程序类Foo,你有两个独立的模块a.hpp和b.hpp都需要Foo.你的主程序必须包含a.hpp和b.hpp,但现在你试图包括foo.hpp,因此包括Foo的类定义两次.
输入包括警卫.
标签:c-3,include-guards,c,header-files,header 来源: https://codeday.me/bug/20190723/1514323.html