Как предотвратить двойное включение файлов заголовков? Проблема в том, что я включаюв MyClass.h, а затем я включаю MyClass.h во многие файлы, поэтому он включается несколько раз, и возникает ошибка переопределения. Как предотвратить?
Я использую #pragma once вместо включения охранников, и я думаю, что это нормально.
MyClass.h:
// MyClass.h
#pragma once
#include <winsock2.h>
class MyClass
{
// methods
public:
MyClass(unsigned short port);
virtual ~MyClass(void);
};
РЕДАКТИРОВАТЬ: несколько ошибок, которые я получаю
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(91) : warning C4005: 'AF_IPX' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(460) : see previous definition of 'AF_IPX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(124) : warning C4005: 'AF_MAX' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(479) : see previous definition of 'AF_MAX'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(163) : warning C4005: 'SO_DONTLINGER' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(402) : see previous definition of 'SO_DONTLINGER'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(206) : error C2011: 'sockaddr' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(485) : see declaration of 'sockaddr'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing '}' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2143: syntax error : missing ';' before 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(384) : error C2059: syntax error : 'constant'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C2143: syntax error : missing ';' before '}'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(437) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(518) : warning C4005: 'IN_CLASSA' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(287) : see previous definition of 'IN_CLASSA'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(524) : warning C4005: 'IN_CLASSB' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(293) : see previous definition of 'IN_CLASSB'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(530) : warning C4005: 'IN_CLASSC' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(299) : see previous definition of 'IN_CLASSC'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(541) : warning C4005: 'INADDR_ANY' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(304) : see previous definition of 'INADDR_ANY'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(543) : warning C4005: 'INADDR_BROADCAST' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(306) : see previous definition of 'INADDR_BROADCAST'
c:\program files\microsoft sdks\windows\v6.0a\include\ws2def.h(577) : error C2011: 'sockaddr_in' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(312) : see declaration of 'sockaddr_in'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(132) : error C2011: 'fd_set' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(68) : see declaration of 'fd_set'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(167) : warning C4005: 'FD_SET' : macro redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(102) : see previous definition of 'FD_SET'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(176) : error C2011: 'timeval' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(111) : see declaration of 'timeval'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(232) : error C2011: 'hostent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(167) : see declaration of 'hostent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(245) : error C2011: 'netent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(180) : see declaration of 'netent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(252) : error C2011: 'servent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(187) : see declaration of 'servent'
c:\program files\microsoft sdks\windows\v6.0a\include\winsock2.h(264) : error C2011: 'protoent' : 'struct' type redefinition
c:\program files\microsoft sdks\windows\v6.0a\include\winsock.h(199) : see declaration of 'protoent'
c++
header
redefinition
акиф
источник
источник
Ответы:
Эта проблема возникает при включении
<windows.h>
ранее<winsock2.h>
. Попробуйте организовать свой список включения, который<windows.h>
включен после<winsock2.h>
или определите_WINSOCKAPI_
первым:#define _WINSOCKAPI_ // stops windows.h including winsock.h #include <windows.h> // ... #include "MyClass.h" // Which includes <winsock2.h>
См. Также это .
источник
<winsock2.h>
в MSVC2008.<windows.h>
включение заставляет его генерировать идентичные ошибки компиляции, как вы указали.#include <winsock2.h> #include <ws2tcpip.h> #include <windows.h>
порядок, и я получал winsock2, файл h не найден. Включенный#define _WINSOCKAPI_
выше всех 3 включает в себя все еще ту же ошибкуКак предполагали другие, проблема в том, когда
windows.h
он был включен раньшеWinSock2.h
. Потому чтоwindows.h
включаетwinsock.h
. Вы не можете использовать обаWinSock2.h
иwinsock.h
.Решения:
Включите
WinSock2.h
раньшеwindows.h
. В случае с предварительно скомпилированными заголовками вы должны решить это там. В случае простого проекта это несложно. Однако в больших проектах (особенно при написании переносимого кода без предварительно скомпилированных заголовков) это может быть очень сложно, потому что, когда ваш заголовокWinSock2.h
включен,windows.h
он уже может быть включен из другого файла заголовка / реализации.Определите
WIN32_LEAN_AND_MEAN
доwindows.h
или спроецируйте в целом. Но это исключит многие другие вещи, которые могут вам понадобиться, и вы должны включить их самостоятельно.Определите
_WINSOCKAPI_
доwindows.h
или спроецируйте в целом. Но когда вы включаете,WinSock2.h
вы получаете предупреждение о переопределении макроса.Используйте
windows.h
вместо того,WinSock2.h
когдаwinsock.h
достаточно для вашего проекта (в большинстве случаев это так). Это, вероятно, приведет к увеличению времени компиляции, но решит любые ошибки / предупреждения.источник
WIN32_LEAN_AND_MEAN
было решением для меня: много танков_WINSOCK_
решении: не следует выдавать предупреждение о переопределении макроса, если оба определения идентичны. Распространенная ошибка заключается в том, что люди добавляют определение в проект, не устанавливая никакого значения, и ожидают пустого определения. Однако, если вы добавите-D_WINSOCK_
в строку cmd, она будет установлена_WINSOCK_
в 1. Чтобы создать пустое определение,-D_WINSOCK_=
необходимо передать.#define _WINSOCKAPI_
, вам также может понадобиться#define _WINSOCK_DEPRECATED_NO_WARNINGS
, в зависимости от ваших обстоятельств.Эх - уродство винды ... Здесь важен порядок включения. Вам необходимо включить winsock2.h перед windows.h. Поскольку windows.h, вероятно, включен из вашего предварительно скомпилированного заголовка (stdafx.h), вам нужно будет включить winsock2.h оттуда:
#include <winsock2.h> #include <windows.h>
источник
Используя «защиту заголовка»:
#ifndef MYCLASS_H #define MYCLASS_H // This is unnecessary, see comments. //#pragma once // MyClass.h #include <winsock2.h> class MyClass { // methods public: MyClass(unsigned short port); virtual ~MyClass(void); }; #endif
источник
Я столкнулся с этой проблемой, когда пытался вытащить сторонний пакет, который, по-видимому, включал windows.h где-то в его беспорядке заголовков. Определить
_WINSOCKAPI_
на уровне проекта было намного проще (не говоря уже о более удобном в обслуживании), чем пробираться через их суп и исправлять проблемное включение.источник
DEFINES += _WINSOCKAPI_
В VS 2015 будет работать следующее:
#define _WINSOCKAPI_
Пока не будет:
#define WIN32_LEAN_AND_MEAN
источник
Я проверил рекурсивный включает, я определил файлы заголовков , которые включают в себя (рекурсивно) некоторые
#include "windows.h"
и#include "Winsock.h"
и написать#include "Winsock2.h"
. в эти файлы я добавил#include "Winsock2.h"
в качестве первого include.Просто проявите терпение, посмотрите на все по очереди и установите этот порядок, сначала
#include "Winsock2.h"
затем#include "windows.h"
источник
Я нашел эту ссылку windows.h и winsock2.h, у которой есть альтернатива, которая отлично мне подходит:
#define _WINSOCKAPI_ // stops windows.h including winsock.h #include <windows.h> #include <winsock2.h>
У меня возникли проблемы с поиском места возникновения проблемы, но, добавив этот #define, я смог построить, не выясняя его.
источник
Я бы не стал использовать только FILENAME_H, но
#ifndef FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD #define FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD //code stuff #endif // FILENAME_H_AF06570D_B36E_4B82_8F97_C456AF4A38FD
Я всегда использовал postfix guid. Несколько лет назад я столкнулся с очень плохой кодовой базой, в которой были разные файлы заголовков с одинаковым именем и включали защиту. В рассматриваемых файлах был определен класс с таким же именем. Если бы использовались только пространства имен. Некоторые проекты собраны, некоторые нет. Использование уникальных защитных элементов было частью решения по различению заголовков и их содержимого.
В Windows с Visual Studio используйте guidgen.exe, в Linux - uuidgen -t.
источник
Я столкнулся с той же проблемой, и вот что я обнаружил до сих пор:
Из этого выходного фрагмента -
-Похоже, что в ваше решение включены и ws2def.h, и winsock.h.
Если вы посмотрите на файл ws2def.h, он начинается со следующего комментария -
/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: ws2def.h Abstract: This file contains the core definitions for the Winsock2 specification that can be used by both user-mode and kernel mode modules. This file is included in WINSOCK2.H. User mode applications should include WINSOCK2.H rather than including this file directly. This file can not be included by a module that also includes WINSOCK.H. Environment: user mode or kernel mode --*/
Обратите внимание на последнюю строчку - «Этот файл не может быть включен модулем, который также включает WINSOCK.H»
Все еще пытаюсь исправить проблему, не внося изменений в код.
Дайте мне знать, если в этом есть смысл.
источник
#pragma once
основывается на полном пути к имени файла. Так что, скорее всего, у вас есть две идентичные копии MyClass.h или Winsock2.h в разных каталогах.источник
Вы должны использовать защиту жатки.
поместите эту строку вверху файла заголовка
#ifndef PATH_FILENAME_H #define PATH_FILENAME_H
и внизу
#endif
источник
#pragma once
является нестабильным, даже на компиляторах MS, и не поддерживается многими другими компиляторами. Как уже упоминали многие другие люди, использование include guards - лучший способ. Ни в коем случае не используйте#pragma once
- это облегчит вам жизнь.источник
#pragma once
компилятор принимает имя узла файла заголовка в качестве уникального идентификатора. Это может потерпеть неудачу, если у вас есть символические ссылки или NTFS-соединения в вашем исходном дереве (чаще, чем вы думаете), или даже если у вас есть файл с тем же именем в другом системном каталоге include (это случалось со мной раньше, когда я версия 1 и версия 2 одной и той же библиотеки, установленной в двух разных системах, включают пути). Итог: для меня я предпочитаю иметь больше контроля и жить с случайными ошибками программного обеспечения, чем доверять компилятору, который сделает это за меня.# включить охранников - стандартный способ сделать это. #pragma once - нет, что означает, что не все компиляторы его поддерживают.
источник
В моем проекте (я использую VS 2008 SP1) работает следующее решение:
Заголовочный файл:
//myclass.h #pragma once #define _WINSOCKAPI_ #include <windows.h>
Класс cpp:
//myclass.cpp #include "Util.h" #include "winsock2class.h" #pragma comment(lib, "Ws2_32.lib")
где #include "winsock2class.h" означает класс, в котором реализован winsock2.h:
//winsock2class.h #include <winsock2.h> #include <windows.h> #pragma comment(lib, "Ws2_32.lib")
источник
На самом деле я столкнулся с проблемой, когда мне пришлось определить winsock2.h как первое включение, похоже, у него есть другие проблемы с включениями из других пакетов. Надеюсь, это будет полезно для тех, кто сталкивается с той же проблемой, не только с windows.h, но и со всеми.
источник