C++:关于重复定义的解决思路

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dashumak/article/details/84326563

一、VC编译原理

解决重定义问题,首先要明白VC的编译原理:

  • VC只编译cpp文件,这些cpp文件构成将来的exe;
  • 当VC编译A.cpp文件的时候,如果遇到了语句#include "B.h",实质上是将"B.h"文件中的代码全部“复制”到A.cpp中,然后再继续编译A.cpp。
  • 当在B.h文件中定义全局变量a等,即使使用了避免文件重复包含的方法(如下节提到的两种方法),是不能避免“A.cpp中#include"B.h",C.pp中#include"B.h",然后提示变量a重复定义”的问题,只能保证“A.cpp中多次出现#include"B.h”而不会提示变量a重复定义”。
  • 全局变量、函数、结构体一定要在.cpp文件中定义,在.h文件中声明,一定不要在h文件中定义,否则会出现重复定义的问题。

二、头文件避免类重复包含的方法

1. 微软预编译控制

#if _MSC_VER > 1000
#pragma once
#endif
... ... // .h文件正文

在.h文件最开始的地方加上这段代码,即可避免头文件重复include。但是需要注意的是#pragma once 这条语句只有VC编译器大于1000才可以支持(反正VC++6.0及以上是可以的),_MSC_VER就是Microsoft的C编译器的版本。
#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。

2、宏定义方式

#ifndef __SOMEFILE_H__
#define __SOMEFILE_H__ 
... ... // .h文件正文
#endif

#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况 。不过如果是编译器自动生成的类一般都会自动根据编译次数(唯一)来自动生成唯一的宏名。

三、出现重复定义的变量的解决方法

在项目同时使用第三方库GuiLib和CJ609Lib,编译提示结构体CMenuItemInfo重定义,后来研究了一下,发现Guilib和CJ609Lib中都全局定义了同一个结构体名CMenuItemInfo,而解决方法有两种:使用宏定义规避和使用命名空间

1.宏定义规避

这种方法很简单,就是类似C++利用宏避免头文件重复的形式,直接给实例,在两个关于CMenuItemInfo结构体定义的位置加上一下的宏定义就行:

#ifndef __CMenuItemInfo_LOCAL_DEFINED//避免结构体CMenuItemInfo重复定义
#define __CMenuItemInfo_LOCAL_DEFINED
struct CMenuItemInfo : public MENUITEMINFO_LOCAL {
    CMenuItemInfo()
    {
        memset(this, 0, sizeof(MENUITEMINFO_LOCAL));
        cbSize = sizeof(MENUITEMINFO_LOCAL);
    }
};
#endif//__CMenuItemInfo_LOCAL_DEFINED

这样做的好处是,用CMenuItemInfo定义具体对象时,直接使用CMenuItemInfo,程序会自动使用编译过程遇到的第一个CMenuItemInfo的定义。
但这种方法有一个前提:两个结构体的定义必须一致,也就是说上述关于CMenuItemInfo的两个定义必须一致,很巧的是Guilib和CJ609Lib关于CMenuItemInfo的定义确实一致。

2.使用命名空间

这种方法更加广泛,尤其适合于重名且定义的内容不一样的情况。这种方法等有时间了,我再在下边补充,本次使用了宏定义就解决了上述问题。
PS:最后补充一点,有的时候提示@.obj已经在@.obj中定义的时候,在项目属性配置中启用预编译头可能会解决这个问题,但不知道是什么原理。

猜你喜欢

转载自blog.csdn.net/dashumak/article/details/84326563
今日推荐