在头文件定义全局变量以后

本文探讨了C++编程中头文件重复包含导致的问题,特别是全局变量定义引起的链接错误,并给出了预防措施。同时介绍了正确使用预编译头文件的方法及在DirectShow编程中GUID的正确定义方式。

 

这样编译时 会出现error:

2.obj : error LNK2005: "unsigned long test" (?test@@3KA) already defined in 1.obj

这是为什么呢?

 #ifndef  #define  #endif

不是可以防止头文件被重复编译,

进一步想 在编译时 是不是以.cpp文件为单位进行的,上述方法只是保证 .cpp内的头文件不被重复包含

后来我做了实验 如上述 不行

我在C1的头文件中加上#include "glo.h"

在C1的CPP中也加上#include "glo.h"

这样C1.CPP包含两个#include "glo.h" 而且"glo.h"中有DWORD 类型的定义

结果是 编译无问题 看来在编译时 是.cpp文件为单位进行的是正确的,即#ifndef #define #endif只在所在的CPP范围内起作用

而且我得出一个结论:
不要在头文件中定义变量,否则 一旦这个头文件包含在多个.CPP时 就会出现上述error

因为同一头文件中变量可以被声明多次,但只能被定义一次。

 

 

 

写directshow程序时,注意在定义guid 时,必须如下: Guidgen.exe , initguid.h , DEFINE_GUID
2008-05-18 16:41

// Src1.cpp #include #include "MyGuids.h" // Src2.cpp #include "MyGuids.h" // Src3.cpp #include "MyGuids.h" 其中在MyGuids.h必须使用 DEFINE_GUID(CLSID_MyObject, 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); (Where this example has zeroes, put the actual GUID values.) You can use the Guidgen.exe utility to create a new GUID and paste it 其中initguid.h只能在一个.cpp中包含, DEFINE_GUID()宏定义了,如果包含了一个initguid.h,那么定义一个guid, 如果没有包含一个initguid.h ,则定义一个extern guid指向定义的那个guid, 所以项目中必须有一个文件.cpp包含initguid.h,否则会出错。但如果包含了多个的initguid.h,也会出错

### C/C++ 全局变量头文件中的正确声明方法和注意事项 #### 1. 使用 `extern` 关键字声明全局变量 为了确保全局变量能够在多个源文件之间共享,而不违反一次定义原则 (One Definition Rule),应当在一个 `.cpp` 文件中定义全局变量,在对应的头文件中仅通过 `extern` 进行声明。 例如: ```cpp // global_var.h #ifndef GLOBAL_VAR_H #define GLOBAL_VAR_H extern int myGlobalVar; #endif // GLOBAL_VAR_H ``` 上述代码片段展示了如何在头文件中声明一个名为 `myGlobalVar` 的全局变量[^2]。这里的关键在于使用了 `extern` 关键字,表明此变量的实际存储空间并不在此处分配,而是在另一个地方定义。 接着,在某个实现文件(`.cpp`)中完成实际的定义: ```cpp // global_var.cpp #include "global_var.h" int myGlobalVar = 42; ``` 这样做的好处是可以防止重复定义错误,并允许不同编译单元访问同一个全局变量实例[^3]。 #### 2. 避免直接在头文件中初始化全局变量 如果尝试直接在头文件定义并初始化全局变量,则每次包含该头文件时都会创建一个新的副本,这通常不是预期的行为,并可能导致链接器报错或未定义行为。 考虑以下不推荐的做法: ```cpp // 错误示范:header.h int myGlobalVar = 10; // 不建议这样做 ``` 当多个源文件包含了这样的头文件时,每个翻译单元都会有自己独立的一份 `myGlobalVar` 变量拷贝,违背了一次定义规则的要求。 #### 3. 对于静态全局变量 (`static`) 的特殊处理 有时可能希望限制某些全局变量的作用范围到单个源文件内部,此时可利用关键字 `static` 来修饰这些变量。然而需注意的是,一旦加上 `static` 属性之后,即使其他文件试图借助 `extern` 去引用它也是不可能成功的,因为它的可见性和生命周期都被限定到了当前文件范围内。 示例代码如下所示: ```cpp // file_with_static_global.cpp static int secretNumber = 7; // 此变量只限本文件内可用 void setSecret(int newValue){ secretNumber = newValue; } int getSecret(){ return secretNumber; } ``` 尽管如此,还是强烈反对轻易改变此类静态全局数据成员的状态,除非确实必要。 #### 4. 推荐实践——封装全局状态 现代编程风格提倡减少裸露的全局变量数量,转而采用类或者命名空间等方式来管理跨模块间的数据交互需求。比如可以通过设计单一职责的服务对象代替传统的自由漂浮型公共资源。 总结来说,合理运用 `extern` 是解决多文件项目里共享同一片内存区域的有效手段之一;同时也要警惕滥用全局变量带来的副作用风险,诸如潜在的竞争条件等问题[^4]。 ```cpp namespace GlobalState { int sharedValue = 0; void updateSharedValue(int value); int retrieveSharedValue(); } ``` 以上模式提供了一种更加结构化的方式来控制对外暴露接口的同时隐藏具体实现细节。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值