gpt4 book ai didi

java - 与 Java 静态 block 等效的 C++ 习语是什么?

转载 作者:IT老高 更新时间:2023-10-28 12:48:09 25 4
gpt4 key购买 nike

我有一个包含一些静态成员的类,我想运行一些代码来初始化它们(假设这段代码不能转换为简单的表达式)。在 Java 中,我会这样做

class MyClass {
static int myDatum;

static {
/* do some computation which sets myDatum */
}
}

除非我弄错了,C++ 不允许这样的静态代码块,对吧?我应该怎么做?

我想要以下两个选项的解决方案:

  1. 在加载进程时(或加载具有此类的 DLL)时发生初始化。
  2. 在第一次实例化类时进行初始化。

对于第二个选项,我在想:

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++(目前?)不允许初始化非常量静态成员。但是,至少这将静态 block 的问题减少到通过表达式进行静态初始化的问题......

最佳答案

您也可以在 C++ 中使用静态 block - 在类之外。

事实证明,我们可以实现 Java 风格的静态 block ,尽管是在类外部而不是在类内部,即在翻译单元范围内。该实现在底层有点丑陋,但使用时却非常优雅!

可下载的版本

现在有一个 GitHub repo解决方案,包含一个头文件:static_block.hpp .

用法

如果你写:

static_block {
std::cout << "Hello static block world!\n";
}

此代码将在您的 main() 之前运行。你可以初始化静态变量或做任何你喜欢的事情。所以你可以在你的类的 .cpp 实现文件中放置这样一个 block 。

注意事项:

  • 必须用花括号将静态 block 代码括起来。
  • 静态代码的相对执行顺序是not guaranteed in C++ .

实现

静态 block 实现涉及使用函数静态初始化的虚拟变量。您的静态 block 实际上是该函数的主体。为了确保我们不会与其他一些虚拟变量(例如来自另一个静态 block - 或其他任何地方)发生冲突,我们需要一些宏机制。

#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__
#ifdef _MSC_VER
#define _UNUSED
#else
#define _UNUSED __attribute((unused))
#endif // _MSC_VER

这里是把东西放在一起的宏观工作:

#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 _UNUSED = (function_name(), 0) ; \
static void function_name()

注意事项:

  • 一些编译器不支持 __COUNTER__ - 它不是 C++ 标准的一部分;在这些情况下,上面的代码使用 __LINE__,它也可以。 GCC 和 Clang 确实支持 __COUNTER__
  • 这是C++98;您不需要任何 C++11/14/17 构造。但是,它不是有效的 C,尽管没有使用任何类或方法。
  • 如果您的 C++11 编译器不喜欢GCC 风格的未使用扩展。
  • 这并不能避免或帮助 static initialization order fiasco ,因为虽然你知道你的静态 block 将在 main() 之前执行,但你不能保证相对于其他静态初始化何时发生这种情况。

Live Demo

关于java - 与 Java 静态 block 等效的 C++ 习语是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19227664/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com