#ifndef 解决局部变量定义的问题——共享文件头导致重定义问题

本文深入探讨了C++中头文件内变量重定义的问题,通过实例分析了#ifndef、const类型以及C语言编译方式在解决此问题上的应用。详细解释了变量在头文件中的作用域及全局作用域内的const变量行为,提供了多种解决方法并总结了最佳实践。

C++ - Shared Header Causes Multiply Defined Symbol Error

今天遇到一个多重定义问题,自己写了个小程序实验了下,

一个头文件head.h定义了一个字符串常量。两个cpp,main.cpp,source.cpp  都include head.h文件

Complie能过Link的时候报错了,vc 报的错误是:error LNK2005: "char const * const pchar" (?pchar@@3PBDB) already defined in main.obj

头文件head.h代码如下:

#ifndef _HEAD_J_H

#define _HEAD_J_H

const char * pchar = "123456";

#endif _HEAD_J_H

思考一:

为什么我已经加了#ifndef了还是会导致 重定义,#ifndef #define ....#endif的作用不是防止重定义么?

跟小菊同学讨论之后,他说#ifndef防止重定义是在单个obj内的,即如果单个cpp文件多次包含某一头问题只会编译一次,但是如果有多个cpp文件,#ifndef只会限制每个cpp文件内的头文件不会包含多次,几个cpp文件之间是不会有影响的。我查了《windows核心编程》这本书里有讲编译链接生成exedll的过程。编译过程中每个cpp都会编译生成一个对应obj文件,链接过程中将每个obj连接起来生成一个可执行文件。我又查了《c++primer》关于#ifndef的内容,里面提到了是为了防止编译过程,看清楚是编译过程中防止头文件被多重定义,所以#ifndef确实只会限制单个obj文件里头文件不被包含多次;


思考二:

我将上面的head.h的代码改为如下的却complielink都成功了

#ifndef _HEAD_J_H #define _HEAD_J_H const char ch = 'd'; #endif _HEAD_J_H

说好的重定义呢?怎么又没了呢?修改之前和修改之后唯一的区别是变量chconst类型,和pchar只是指向const 内容的指针,却不是const 类型指针, 于是乎我又将代码改为如下:

#ifndef _HEAD_J_H #define _HEAD_J_H //void func(); const char * const pchar = "123456"; #endif _HEAD_J_H

将指针也变为const类型,就又成功了。照理说 既然我这么定义在头文件里 肯定是global变量了,在main.cpp里定义了一次在source.cpp里定义了一次,在链接obj的时候发现有两个 同样的变量,这个时候必然会报重定义错误。但是改为const类型之后为什么不报错了呢,我去查了《c++primer》里面有关const内容的,里面有一段话是大致是这样写的:

C++中的const对象默认为文件的局部变量,与其他变量不同,不特殊申明的话,在全局作用域内的const变量定义该对象文件的局部变量,此变量只存在于那个文件中,不能被其他文件访问,其他文件访问需要加extern

看了上面的解释,相信大家也都知道了原因了,既然作为局部变量了,几个cpp文件link的时候当然不会出错了。这也是const的特性吧,这是一种解决 头文件里变量重定义的方法;


思考三:

我们大部分在头文件里定义 变量 基本都是常量,大家可以用#define 宏定义来解决问题,宏定义 内容是存储在代码段的,在编译之前做文本替换。宏定义的一个确定 就是 类型检查 ,各有优弊吧,大家自行选择;


思考四:

在网上搜索资料的时候还发现了一种方法,就是将cpp文件改为.c文件,这样就会按照语言编译,在C语言中,如果遇到多个 比如说是 int i 吧,会将第一个作为定义,其他的都作为声明,所以不会出错;


总结:一般来说C++里不建议你在头文件里定义变量的,所以大家还是能移则移到cpp吧,然后用extern来支持多个文件访问;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值