推荐的C ++语法与Java静态块相当吗? [英] What's the recommended C++ idiom equivalent to the Java static block?

查看:105
本文介绍了推荐的C ++语法与Java静态块相当吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  class MyClass {
static int myDatum;

static {
/ *做一些计算,设置myDatum * /
}
}

除非我错了,C ++不允许这样的静态代码块,对吧?



我想为以下两个选项提供解决方案:


  1. 初始化发生在进程加载时(或者加载此类的DLL时)。

  2. 初始化在类首次实例化时发生。

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

  StaticInitialized {
static bool staticsInitialized = false;

virtual void initializeStatics();

StaticInitialized(){
if(!staticsInitialized){
initializeStatics();
staticsInitialized = true;
}
}
};

class MyClass:private StaticInitialized {
static int myDatum;

void initializeStatics(){
/ *计算设置myDatum * /
}
};

但是这是不可能的,因为C ++(目前?)不允许初始化非const静态成员。但是,至少通过表达式将静态块的问题减少到静态初始化的问题...

解决方案

完成和使用就像在Java!



使用



如果你写: / p>

  static_block {
std :: cout< Hello static block world! << std :: endl;
}

此代码将在 main() / code>。



注意




  • 必须用大括号括住静态块代码。

  • 静态代码的相对执行顺序为



实施 h3>

静态块实现涉及使用函数静态初始化的虚拟变量。你的静态块实际上是该函数的主体。为了确保我们不会碰到一些其他虚拟变量(例如从另一个静态块或任何其他地方),我们需要一些宏观机制。

  #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 * /
#else
#endif / * UNIQUE_IDENTIFIER * /

,这里是把工作放在一起的宏工作:

  #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 ,var_name)\
static void function_name(); \
static int var_name __attribute((unused))=(function_name(),0); \
static void function_name()

注意: / p>


  • 某些编译器不支持 __ COUNTER __ (因为它是标准的扩展,部分)。在这些情况下,您使用 __ LINE __ ,这也工作。 GCC和Clang支持 __ COUNTER __

  • 这是C ++ 98;你不需要任何C ++ 11/14/17构造。

  • 如果你有一个__attribute((未使用))可以删除或替换为[[未使用]



我在实际工作中使用这个,因此您可以从这里获取.h文件。 / a>。


I have a class with some static members, and I want to run some code to initialize them (suppose this code cannot be converted into a simple expression). In Java, I would just do

class MyClass {
    static int myDatum;

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

Unless I'm mistaken, C++ does not allow for such static code blocks, right? What should I be doing instead?

I would like solution for both of the following options:

  1. Initialization happens when process loads (or when the DLL with this class is loaded).
  2. Initialization happens when the class is first instantiated.

For the second option, I was thinking of:

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 */
    }
};

but that's not possible, since C++ (at the moment?) does not allow initialization of non-const static members. But, at least that reduces the problem of a static block to that of static initialization by expression...

解决方案

It can be done, and used just like in Java! Under the hood things are not incredibly elegant, but not that bad.

Usage

If you write:

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

this code will run before your main().

Notes:

Implementation

The static block implementation involves a dummy variable initialized statically with a function. Your static block is actually the body of that function. To ensure we don't collide with some other dummy variable (e.g. from another static block - or anywhere else), we need a bit of macro machinery.

#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 */
#else
#endif /* UNIQUE_IDENTIFIER */

and here is the macro work to put things together:

#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()

Notes:

  • Some compilers does not support __COUNTER__ (as it's an extension to the standard, not part of it); in those cases you use __LINE__, which works too. GCC and Clang support __COUNTER__.
  • This is C++98; you don't need any C++11/14/17 constructs.
  • The __attribute ((unused)) can be dropped, or replaced with [[unused]] if you have a C++11 compiler which doesn't like the GCC-style unused extension.

I'm using this in my actual work, so you can grab it as a .h file from here.

这篇关于推荐的C ++语法与Java静态块相当吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆