我正在尝试使用 GCC,发现您可以在头文件中声明变量
const
,但在实现文件中保持它们可变。
编辑:这实际上不起作用,请检查我自己的答案。
标题.h:
#ifndef HEADER_H_
#define HEADER_H_
extern const int global_variable;
#endif
标题.c:
int global_variable = 17;
这使得
global_variable
可以修改实现,但 const
可以修改到包含 header.h
的每个文件。
#include "header.h"
int main(void)
{
global_variable = 34; /* "header.h" prevents this type of assignment. */
return 0;
}
这个技术在实践中有应用吗?
人们经常建议在用 C 语言构建接口时使用
get
函数来检索全局状态。与此相比,这种方法有什么优点吗?
对我来说,这种方法似乎更清晰,并且每次有人尝试访问时都不会增加函数调用的开销
global_variable
。
这两种方法都在实践中使用,但大多数情况下的最佳实践是避免全局变量和静态状态。
注意:你的问题被标记为C和C++,这是C++方法。
更好的方法是创建一个包含“全局”状态的类,并将其传递给需要全局变量和常量的函数。这称为“上下文”。
上下文对象可以使用适当的信息隐藏来控制谁可以更新其状态、验证其状态等,就像任何其他对象一样。另外,它完全避免了对全局变量的需要,这是一种反模式。
举这个例子。
标题.h:
#ifndef HEADER_H_
#define HEADER_H_
extern const int global_variable;
#endif
标题.c:
#include "header.h"
int global_variable; // Here will the compiler complain!
这不会编译,因为
int
和 const int
不是兼容的类型。我自己的测试工作的唯一原因是因为我NOT在“header.c”中包含“header.h”。
get
函数允许稍后插入新逻辑(例如验证)。如果您从全局变量开始,后来发现您需要新的逻辑,那么添加 get
函数就是一个重大更改。
这是 C++11 之前的做法,可能存在一些缺陷:事实上,它依赖链接器来维持解析。如果所有值都很简单,那么这不是一个大问题,但如果一个值不是 POD 并且依赖于其他值,由于链接顺序不是由源指定的,这可能会暴露于“全局初始化失败”。
在头文件内部有时可能有更直接的方法a
static constexpr int global_constant = xx;
static 关键字使
global_constant
本地化到每个独立的翻译单元,避免了只定义一次“通用全局对象”的需要。
此方法还与“仅标头库”兼容,这是通用代码必须的。