我有一个包含一些静态成员的类,我想运行一些代码来初始化它们(假设这段代码不能转换为简单的表达式)。在Java中,我会做
class MyClass {
static int myDatum;
static {
/* do some computation which sets myDatum */
}
}
除非我弄错了,C++ 不允许这样的静态代码块,对吧?我应该怎么做?
我想要以下两个选项的解决方案:
- 初始化发生在进程加载时(或加载具有此类的 DLL 时)。
- 初始化发生在第一次实例化类时。
对于第二个选项,我在考虑:
class StaticInitialized {
static bool staticsInitialized = false;
virtual void initializeStatics();
StaticInitialized() {
if (!staticsInitialized) {
initializeStatics();
staticsInitialized = true;
}
}
};
class MyClass : private StaticInitialized {
static int myDatum;
void initializeStatics() {
/* computation which sets myDatum */
}
};
但这是不可能的,因为 C++(目前?)不允许初始化非常量静态成员。但是,至少这将静态块的问题减少为通过表达式进行静态初始化的问题……
原文由 einpoklum 发布,翻译遵循 CC BY-SA 4.0 许可协议
您也可以在 C++ 中使用静态块 - 外部类。
事实证明,我们可以实现 Java 风格的静态块,尽管是在类之外而不是在类内部,即在翻译单元范围内。该实现在引擎盖下有点难看,但使用时非常优雅!
可下载版本
现在有一个解决方案的 GitHub 存储库,包含一个头文件:
static_block.hpp
。用法
如果你写:
此代码将在您的
main()
之前运行。你可以初始化静态变量或做任何你喜欢的事情。所以你可以在你的类中放置这样一个块’.cpp
实现文件。笔记:
执行
静态块实现涉及使用函数静态初始化的虚拟变量。您的静态块实际上是该函数的主体。为了确保我们不会与其他一些虚拟变量(例如来自另一个静态块 - 或其他任何地方)发生冲突,我们需要一些宏机制。
这是将事物放在一起的宏观工作:
笔记:
__COUNTER__
- 它不是 C++ 标准的一部分;在这些情况下,上面的代码使用__LINE__
,它也有效。 GCC 和 Clang 确实支持__COUNTER__
。__attribute ((unused))
可能会被删除,或者替换为[[unused]]
如果你有一个不喜欢 GCC 风格的未使用扩展的 C++11 编译器。main()
之前执行,但不能保证相对于其他静态初始化何时发生这种情况。现场演示