当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 文件重定义冲突的分析与解决

VC++
在类VC的界面实现中加入目录树
软件换肤技术在 BCB 中的实现
利用非模窗口生成MDI介面
报表输出轻松搞定
Windows 中不规则窗体的编程实现
解说Win32的窗口子类化
使用测试优先方法开发用户界面
一个简单的登录对话框的实现
一个简单的日记本程序
从资源中加载皮肤
一个在RichEdit中添加表情图象的类
ActiveSkin 4.3 软件换肤在VC中的实现
一种另类“关于(About)”对话框的动态显示方法
对话框打印预览及打印
关于如何换肤、子类化的解决方案
制作 MSN、QQ 的消息提示窗口
如何对 BCGControlBarPro 进行换肤
定制个性化的对话框窗口类
改变窗口中的光标形状
更新MFC中的视图,跟踪.NET Framework中的事件

VC++ 中的 文件重定义冲突的分析与解决


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 84 ::
收藏到网摘: n/a

文件重定义冲突的分析与解决

作者:hrg21


引言


  有时候看到论坛上有人问编译时重定义现象的问题。这个问题与头文件包含冲突有关,改一改相关头文件包含就会让问题消失。我在这里要以 <windows.h> <winsock.h> <winsock2.h>这3个头文件为例分析为什么会产生这种原因;然后给出一种不会产生冲突的做法;最后就此例的分析给出结论。本文对于已经知道冲突原因的读者是多余的,但对于一时没有时间去解的人还是有一定的参考价值的。


一个重命名的例子

先写一个socket基本操作类:

// SocketBase.h#ifndef _SOCKET_BASE_H_#define _SOCKET_BASE_H_#include <winsock2.h>#pragma comment(lib, "ws32_2.lib")class Socket{};#endif
写一个TCP监听类,它从Socket派生:
// TcpListener.h #ifndef _TCP_LISTENER_H_#define _TCP_LISTENER_H_#include "SocketBase.h"class TcpListener : Socket{};#endif
在基于MFC的工程中用 TcpListener 监听客户连接,同时这个地方须要用到 Windows 某些头文件。
#include "stdafx.h" #include "TcpListener.h"void fun(){ TcpListener* listen = new TcpListener; ……}
下面是头文件包含关系:
Stdafx.h -> windows.h -> winsock.h winsock2.hTcpListener.h -> SocketBase.h -> winsock2.h
  编译,出现N多重定义错误。这个错误与stdafx.h中的 windows.h 和TcpListener.h 的winsock2.h 有关,下面说两种消除错误的方法。


针对本工程中消除编译

错误产生的原因是 windows.h 中有:
 #include <winsock.h> #include <winsock2.h>
  产生重定义的是 windows.h 中的 winsock.h 相关定义与 TcpListener.h 中 winsock2.h 相关定义冲突。相同头文件是不会冲突的,因为有 "#ifndef #define …. #endif";如果windows中只包含一个winsock2.h就不会产生重定义了。
  现在我们只要把 SocketBase.h 中的 "include <winsock2.h> 和 #pragma…"注释了就编译通过了。但经过注释的 SocketBase.cpp 与 TcpListener.cpp 单独编译就通不过了。这种只是针对特定的环境下解决问题,我们得想一个比较专业的办法。


一个可被接受的解决方法

  Winsock2.h 与 windows.h 中的 winsock.h 相关项的重定义要在 SocketBase.h 中避免。在 SocketBase.h加一些编译条件就可以做到这一点,经过修改的 SockBase.h 如下:
#ifndef _SOCKET_BASE_H_#define _SOCKET_BASE_H_#ifndef _WINSOCKAPI_ // 没有包含winsock.h#define _WINSOCKAPI_ // 避免再包含winsock.h #ifndef _WINSOCK2API_ // 没有包含winsock2.h #define _WINSOCK2API_ // 避免再包含winsock2.h #include <winsock2.h> #pragma comment(lib, "ws32_2.lib") #endif#endifclass Socket{};#endif
经过这样修改,就能做到 winsock.h 与 winsock2.h 中的相关项重定义了。


结论

  通过对上述例子的分析解决,同样在其它类似的问题中适用。如果有更简单的方法避免重定义的情况出现,请告诉我一下。


参考
  • Win32 sdk中的 windows.h;
  • Win32 sdk中的 winsock.h;
  • Win32 sdk中的 winsock2.h;