Сценарий непрямого включения C

#c

#c

Вопрос:

Хорошо, у меня есть этот сценарий.

Класс с именем a, который включает windows.h.

 #ifndef a.h
#define a.h

#include <windows.h>

class a
{
};
#endif
  

Класс с именем b, который включает windows.h.

 #ifndef b.h
#define b.h

#include <windows.h>

class b
{
};
#endif
  

Основной класс как таковой.

   #include "a.h"
  #include "b.h"

  MAIN STUFF
  

Я хотел бы прояснить следующий момент.

Поскольку я импортирую как a, так и b в main, я обеспокоен тем, что windows.h включается дважды. Так ли это? Если да, то как исправить?

Комментарии:

1. Включите их в соответствующие исходные файлы.

2. Классы ничего не включают.

3. @Махеш. Да, как для класса a, так и для класса be требуется windows.h, поскольку они используют функции, зависящие от windows.h.

4. @Mahesh: Потому что его заголовкам нужен доступ к некоторым символам из WinAPI …?

5. @Mahesh: Это ужасный поступок. Если файлу необходим символ WinAPI, он должен включать заголовок WinAPI. Он абсолютно не должен полагаться на что-то другое, что включало его, чтобы также ранее включало заголовок WinAPI. Заголовки должны быть самодостаточными. (Кроме того, в чем проблема ? Здесь нет проблемы.)

Ответ №1:

#windows.h должен быть (читай: является) достаточно умным, чтобы это не было проблемой.

  • Они используют «защитные элементы заголовка», чтобы гарантировать безопасность многократного включения в TU, так же, как вы делали в своих файлах a.h и b.h (хотя вам действительно следует выбрать лучшие имена для этих защитных элементов… о, как легко они могут конфликтовать в настоящее время!).

  • Чтобы гарантировать безопасность множественного включения в TU (на данный момент это не ваш сценарий), они ограничиваются разрешением только объявлений, а не определений, в файлах заголовков. Остальное будет размещено в двоичных файлах библиотеки, которые являются частью вашей операционной системы. (И, фактически, помимо определений шаблонов / встроенных функций, вы всегда должны отклоняться от определения вещей в заголовках).

Комментарии:

1. «они» = тот, кто написал windows.h

2. Итак, вы предлагаете, чтобы я #включил <windows.h> в файл cpp, а не в файл h? Я не понимал, что это имеет значение.

3. @user440297: Абсолютно нет. Как сказано в моей первой строке, «это не проблема». Оставьте ваш код таким, какой он есть. Извините, если это было непонятно…

4. Ах, спасибо. Просто некоторая затяжная путаница из-за комментария Махеша, но теперь все ясно.

Ответ №2:

Взгляните на первые две строки в ваших собственных файлах заголовков. Вместе эти строки гарантируют, что препроцессор C включает каждый файл заголовка только один раз. Это стандартный способ написания заголовков для программного обеспечения на C / C . Заголовки основных систем, такие как windows.h, делают то же самое (или что-то подобное), чтобы убедиться, что препроцессор видит файл только один раз.

Ответ №3:

Не должно быть никаких проблем, поскольку windows.h во включаемом файле есть защитные элементы. Если вы получаете ошибки, переключите версии компилятора или компиляторы в целом.

Ответ №4:

windows.h не включается более одного раза.

действительно, заголовочные файлы c / c используют соглашение о защите включения с помощью защитного блока #ifdef, подобного этому:

 #ifndef __WINDOWS_H__
#define __WINDOWS_H__
...
... <windows.h content>
...
#endif
  

так что на самом деле включено только один раз

Ответ №5:

Да, но не беспокойтесь, поскольку запуск windows.h является:

 #ifndef _WINDOWS_
#define _WINDOWS_
  

Кроме того, вы, возможно, захотите также

 #define WIN32_LEAN_AND_MEAN
  

перед включением Windows, чтобы исключить некоторые из более эзотерических функций.

Ответ №6:

Я на 99% уверен, что у этого windows.h есть защита от включения, поэтому должно быть абсолютно безопасно включать a.h и b.h в один файл — вещи в windows.h не будут дублироваться

Комментарии:

1. Если вы уверены только на 99%, то это безопасно только на 99%. 🙂

2. Ну, передо мной нет windows.h , но я был бы очень, тотально, крайне удивлен, если бы это было не так (:

3. @Kiril: Конечно, но считать что-то «абсолютно безопасным», если вы уверены только на 99%, — это плохая практика программирования, не так ли?

4. Правильно, я добавил «должно быть», ок (:. Но если это не так, это будет означать, что «windows» нажимает на спусковой крючок при включении windows.h в ваш проект ( «Любой язык позволит вам выстрелить себе в ногу. C предоставит пистолет, зарядит патроны, даст вам выпить, чтобы ваша рука не дрожала, установит оптический прицел и нарисует большую мишень на вашей ноге » )

5. «плохая практика программирования» — хорошо, вы должны всегда проверять все, что вы используете, верно. Но вы пытаетесь сказать мне, что вы всегда на 100% уверены в каждой отдельной строке, которую вы пишете в своем коде? Потому что я сомневаюсь в этом. (:

Ответ №7:

Это не должно быть проблемой, потому что важный файл заголовка, подобный Windows.h , также будет содержать защиту в начале, например

 #ifndef _WINDOWS_H
#define _WINDOWS_H

//...code

#endif // _WINDOWS_H
  

Таким образом, информация в Windows.h заголовочном файле будет включена только один раз для каждого скомпилированного модуля кода, даже если заголовок повторяется несколько раз, поскольку после первого включения он _WINDOWS_H определен, поэтому защитные средства заставляют препроцессор пропускать содержимое оставшихся Windows.h файлов.