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
Здесь нет проблем.
ОБНОВЛЕНИЕ: вставьте заголовок в охранники (извините, это была ошибка).