在头文件中使用“extern const”使全局变量只读

64jmpszr  于 2024-01-06  发布在  其他
关注(0)|答案(4)|浏览(286)

我在尝试GCC,发现你可以在头文件中声明变量const,但在实现文件中保持可变。

header.h:

  1. #ifndef HEADER_H_
  2. #define HEADER_H_
  3. extern const int global_variable;
  4. #endif

字符串
header.c:

  1. int global_variable = 17;


这使得global_variable对于实现是可修改的,但是const对于包含header.h的每个文件都是可修改的。

  1. #include "header.h"
  2. int main(void)
  3. {
  4. global_variable = 34; /* "header.h" prevents this type of assignment. */
  5. return 0;
  6. }


这种技术是否在实践中使用?
在C中构建接口时,人们经常建议使用get-函数来检索全局状态。这种方法有什么优点吗?
对我来说,这种方法似乎更清晰,并且每次有人试图访问global_variable时都不会增加函数调用的开销。

ufj5ltwl

ufj5ltwl1#

这两种方法在实践中都有使用,但大多数情况下的最佳实践是避免全局变量和静态。
注意:你的问题标记为C和C++,这是C++的方法。
更好的方法是创建一个包含“全局”状态的类,并将其传递给需要全局变量和常量的函数,这称为“上下文”。
上下文对象可以使用适当的信息隐藏来控制谁可以更新它的状态,验证它的状态等,就像任何其他对象一样。另外,它完全避免了对全局变量的需要,这是一个反模式。

tyky79it

tyky79it2#

实际无效。

举个例子。
header.h:

  1. #ifndef HEADER_H_
  2. #define HEADER_H_
  3. extern const int global_variable;
  4. #endif

字符串
header.c:

  1. #include "header.h"
  2. int global_variable; // Here will the compiler complain!


这将无法编译,因为intconst int是不兼容的类型。我让自己的测试工作的唯一原因是因为我没有包括“header.h”在“header.c”中。

展开查看全部
9vw9lbht

9vw9lbht3#

get函数允许以后插入新的逻辑(例如验证)。如果你从一个全局变量开始,后来发现你需要新的逻辑,添加一个get函数是一个突破性的变化。

jdg4fx2g

jdg4fx2g4#

这是一种C++11之前的方法,可能有一些缺陷:实际上它依赖于链接器来维持解析。如果所有值都很简单,这不是一个大问题,但是如果一个值不是POD并且依赖于其他值,因为链接顺序不是由源指定的,这可能会暴露于“全局初始化失败”。
在头文件中,它有时可能有一个更直接的方法,

  1. static constexpr int global_constant = xx;

字符串
static关键字使得global_constant对于每个独立的翻译单元是本地的,从而避免了仅定义一次“通用全局对象”的需要。
这种方法也与“Header only libraries”兼容,这是泛型代码必须的。

相关问题