Проблемы с C ++ Header Guard - PullRequest
       40

Проблемы с C ++ Header Guard

2 голосов
/ 19 мая 2010

Я делаю небольшой фреймворк C ++, который содержит много .h и .cpp.

Я создал общее включение, включающее все мои файлы .h, например:

framework.h

#include "A.h"
#include "B.h"
#include "C.h"

каждый заголовок .h защищен включением защиты, таким как

#ifndef A_HEADER
#define A_HEADER
...
#endif

Проблема в том, что я хотел бы иметь возможность включать "framework.h" во все sub .h, например, но это вызывает много ошибок компилятора:

#ifndef A_HEADER
#define A_HEADER

#include "framework.h"
...
#endif

Если вместо этого я использую реальный заголовочный файл для каждого подзаголовка, и framework.h для того, что когда-либо использовало мою инфраструктуру, это работает нормально.

Я просто хотел бы включить основной заголовок во все мои sub .h, поэтому мне не нужно каждый раз включать всю зависимость.

Спасибо:)

Ответы [ 6 ]

7 голосов
/ 19 мая 2010

В основном то, что вы делаете, это #include "A.h" в framework.h и #include "framework.h" в A.h. Это вызывает циклическую зависимость заголовочных файлов, и вы получите ошибки, такие как неопределенный класс A. Чтобы решить эту проблему, используйте предварительные объявления в заголовочном файле и #include только в соответствующем файле cpp. Если это невозможно, я не вижу других вариантов, кроме включения отдельных заголовочных файлов.

2 голосов
/ 19 мая 2010

Вы не должны включать основной файл заголовка в файлы подзаголовка. Его следует использовать для облегчения жизни пользователя, а не вашей.

Вместо этого сделайте следующее:

1) Сделайте предварительные определения всего, что вам нужно, в соответствующих файлах подзаголовков.

2) Включить только необходимые файлы подзаголовка в файлы CPP.

3) При использовании вашей инфраструктуры внутри кода приложения (например), вы можете включить основной заголовочный файл платформы.

2 голосов
/ 19 мая 2010

Просто защитите основной заголовок с помощью включаемых защит:

#ifndef FRAMEWORK_H
#   define FRAMEWORK_H
#   include <A.h>
#   include <B.h>
#   include <C.h>
#endif

Это предотвратит рекурсивное включение.

0 голосов
/ 19 мая 2010

Циркулярные включения вообще плохая идея в C ++. Хотя защита заголовка предотвратит переход препроцессора в бесконечный цикл (или вызовет ошибку из-за этого), вы получите неожиданные ошибки компилятора, потому что в какой-то момент файл заголовка не будет включен, если вы так думаете.

Вы должны включить A.h, B.h и C.h из framework.h, а в A.h не включать framework.h, просто объявите классы, которые вы используете из него. Или сделайте это наоборот: включите framework.h из A.h, B.h и C.h и объявите классы forward в framework.h. И, конечно же, поместите каждый код, который потребует более подробных объявлений, чем, например, class A, в файлы .cpp.

0 голосов
/ 19 мая 2010

Полагаю, у вас есть зависимость между - скажем, B и C, такая, что B зависит от C, но в framework.h C включен после B.

0 голосов
/ 19 мая 2010

Я бы порекомендовал использовать # pragma один раз и поместить его в начало всех ваших заголовочных файлов (framework.h, A.h, B.h и C.h).

Хотя, если вы предпочитаете, я думаю, что вы могли бы решить вашу проблему, просто добавив include guard в framework.h.

...