Introduction
Sometimes you see people on the forums asking questions about compile-time redefinition. This problem is related to the header file containing the conflict, and changing the related header file contains the problem and disappears. I'm here to take the <windows.h> <winsock.h> <winsock2.h> these 3 header files for an example to analyze why this is the case, and then give a practice that does not produce conflict, and finally give a conclusion on this example. This article is superfluous to the reader who already knows the cause of conflict, but there is some reference value for the person who has no time to solve it.
An example of renaming
First write a socket basic operation class:
SocketBase.h
#ifndef _socket_base_h_
#define _socket_base_h_
#include <winsock2.h>
#pragma comment (lib, "Ws32_2.lib")
Class Socket
{
};
#endif
Write a TCP listener class that derives from the socket:
TcpListener.h
#ifndef _tcp_listener_h_
#define _tcp_listener_h_
#include "SocketBase.h"
Class Tcplistener:socket
{
};
#endif
Use TcpListener to listen for client connections in MFC based projects, and this place requires some Windows header files.
#include "stdafx.h"
#include "TcpListener.h"
void Fun ()
{
tcplistener* listen = new TcpListener;
......
}
The following is a header file containing a relationship:
Stdafx.h-> windows.h-> winsock.h winsock2.h
TcpListener.h-> SocketBase.h-> winsock2.h
compilation, an n multiple definition error occurred. This error is related to the winsock2.h of Windows.h and TcpListener.h in StdAfx.h, and the following two ways to eliminate the error.
Elimination of compilation for this project
Errors are caused by windows.h:
#include <winsock.h>
#include <winsock2.h>
What is redefined is that the winsock.h correlation definition in windows.h conflicts with winsock2.h related definitions in TcpListener.h. The same header file does not conflict because there is a "#ifndef #define ... #endif"; If Windows contains only one winsock2.h, no redefinition will occur.
Now we just have to compile the "include <winsock2.h> and #pragma ..." annotation in SocketBase.h. But the annotated SocketBase.cpp and TcpListener.cpp are not going to be compiled alone. This is only to solve the problem in a specific environment, we have to think of a more professional approach.
A solution that can be accepted
The redefinition of winsock.h dependencies in Winsock2.h and windows.h is to be avoided in SocketBase.h. This can be done by adding some compilation conditions in SocketBase.h, and the modified SockBase.h is as follows:
#ifndef _socket_base_h_
#define _socket_base_h_
#ifndef _winsockapi_//No winsock.h included
#define _WINSOCKAPI_//avoid including winsock.h
#ifndef _winsock2api_//No winsock2.h included
#define _WINSOCK2API_//avoid including winsock2.h
#include <winsock2.h>
#pragma comment (lib, "Ws32_2.lib")
#endif
#endif
Class Socket
{
};
#endif
As a result of this modification, WINSOCK.H is redefined with the related items in Winsock2.h.
Conclusion
By analyzing the above examples, it is also applicable to other similar problems. If there is a simpler way to avoid redefining the situation, please let me know.
Reference
Win32 SDK in the windows.h;
Win32 SDK in the winsock.h;
Win32 SDK in the winsock2.h;