您也可以在C ++中具有静态块-外部类。
事实证明,我们可以实现Java样式的静态块,尽管它是在类外部而不是在类内部,即在翻译单元范围内。内幕的实现有点丑陋,但是使用起来非常优雅!
可下载的版本
该解决方案现在有一个GitHub存储库,其中包含一个头文件:
static_block.hpp。
用法
如果您写:
static_block { std::cout << "Hello static block world!n";}此代码将在您的之前运行
main()。您可以初始化静态变量,也可以执行其他任何操作。因此,您可以在类的
.cpp实现文件中放置这样的块。
笔记:
- 您 必须 用花括号将静态块代码括起来。
- 在C ++中不能保证执行静态代码的相对顺序。
实作
静态块实现涉及使用函数静态初始化的虚拟变量。您的静态块实际上是该函数的主体。为了确保我们不会与其他虚拟变量发生冲突(例如,来自另一个静态块或其他任何地方),我们需要一些宏机制。
#define ConCATENATE(s1, s2) s1##s2#define EXPAND_THEN_ConCATENATE(s1, s2) ConCATENATE(s1, s2)#ifdef __COUNTER__#define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_ConCATENATE(prefix, __COUNTER__)#else#define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_ConCATENATE(prefix, __LINE__)#endif // __COUNTER__
这是将内容组合在一起的宏工作:
#define static_block STATIC_BLOCK_IMPL1(UNIQUE_IDENTIFIER(_static_block_))#define STATIC_BLOCK_IMPL1(prefix) STATIC_BLOCK_IMPL2(ConCATENATE(prefix,_fn),ConCATENATE(prefix,_var))#define STATIC_BLOCK_IMPL2(function_name,var_name) static void function_name(); static int var_name __attribute((unused)) = (function_name(), 0) ; static void function_name()
笔记:
- 一些编译器不支持
__COUNTER__
-它不是C 标准的一部分;它不支持C 。在这种情况下,以上代码__LINE__
也会使用。GCC和Clang支持__COUNTER__
。 - 这是C 98;您不需要任何C 11/14/17构造。但是,即使不使用任何类或方法,它 也不是 有效的C语言。
- 该
__attribute ((unused))
可被丢弃,或更换[[unused]]
,如果你有一个C ++编译器11,其不喜欢的GCC风格的未使用的扩展。 - 这不会避免或不利于静态初始化顺序fiasco,因为虽然您知道静态块将在之前执行
main()
,但不能保证相对于其他静态初始化确切的执行时间。
Live Demo



