众所周知c++缺少一个重要的机制,类成员静态初始化构造函数,如下例
class foo
{
private:
static int m_i =0;  //这一句会报错
static const int m_j = 1; //ok
};
我们必需改成在cpp文件中加上 int foo::m_i =0;
现在问题来了,假如程序员A写了一个库,它用到了类静态成员,那么客户程序员需要在他的代码中对其进行初始化,但是如果有多个程序员都分别用到这个库,并且他们都共同完成同一个程序,会有什么样的问题呢?我想灾难是最好的形容。因此我想大部分的c++程序员希望有一个类似于C#中的静态成员初始化构造函数吧,如下
class foo
{
public:
   static foo()
   {...} 
};
但目前c++标准好象并没有想法去支持它!我想了很久提出一种解决办法,大家看看如何
1) 利用函数体内的局部静态变量
2) 利用古老的宏
具体定义如下:#define STATIC_VAL(type,valname,initval) \
static type & static_m_##valname() \
{ \
    static type m_##valname = initval; \
return m_##valname; \
}
#define STATIC_VAL_REF(valname) static_m_##valname()
class CTest
{
public:
    CTest()
{
++ STATIC_VAL_REF(i);
} ~CTest()
{
-- STATIC_VAL_REF(i);
} int get_i()
{
return STATIC_VAL_REF(i);
} static void print()
{
printf("%s\n",STATIC_VAL_REF(msg));
}
private:

STATIC_VAL(int,i,0)
    STATIC_VAL(const char*,msg,"this is")
};STATIC_VAL:完成静态变量的定义
STATIC_VAL_REF 取得静态变量的引用大家觉得这种方法有什么弊端么,另外我不是很清楚,如果在一个DLL中,函数体内的静态变量初使化是在什么时候。

解决方案 »

  1.   

    呃,静态变量最好不要暴露给外界。
    可以将静态变量改成类实现cpp的匿名空间的全局变量.dll中的静态变量初始化在DllMain之前。
      

  2.   

    静态成员变量初始化在dllmain之前,可以提供静态成员函数等来访问,读取静态成员变量
      

  3.   

    1楼没有明白我的意思呀我这段演示代码的目的是达到不需要客户程序员去初始化的一个类的静态成员我们知道在EXE中,类的静态成员初始化是由运行时去完成的,
    但是我不是很清楚象函数体内的静态变量初始化时机它是函数第一次运行时才进行呢,还是由CLR在调用main之前完成这里面区别很大,因为对于DLL就不存CLR的初始化了!!!
      

  4.   

    vc运行时库会在进入main之前进行初始化,所以才要你在cpp中全局初始化
      

  5.   

    没看清楚楼主试图在类定义中初始化静态变量的意图。在类中定义静态变量,在cpp文件中初始化静态变量,我没有觉得有什么不好的。如果涉及多线程的话,线程中的类对象的静态变量不是安全的。
      

  6.   

    刚翻了翻资料,并写了一点代码测试一下,至少有两点是清晰的1、函数体内的局部静态变量初始化是第一次调用该函数才进行初始化,
    2、局部静态变量是非线程安全的,主要是指在初始化时有可能被线程切出去,从而导致多次初始化不清楚的是局部静态变量的析构发生在什么时候,由谁来调用析构
    资料上是说程序结束时,
    是main返回后,由clr来调用析构还是什么的,
    在dll在又会是如何的呢?akirya 你说的类静态变量不要由用户来写初始化,那么我问你
    你的类用于 dll中时,类静态成员初始化时机是在什么时候?
      

  7.   

    静态变量在DLL的生存周期开始的第一个使用者
      

  8.   

    总算找到了完整的说明,呵呵
    相关资料来自于《windows核心编程》--Jeffery Richter。
    当使用VC来建立DLL时,C++运行时库提供启动和析构支持。首先DLL的真正入口并不是DllMain,,而是一个叫做_DllMainCRTStartup的函数。
    1)当DLL文件映射至进程空间地址时,系统将调用这个函数,它初始化C/C++运行时库,并确保收到DLL_PROCESS_ATTACH通知时,创建任何全局或者静态c++对象(此时类的静态成员也会构建),然后调用DllMain,
    2)当DLL收到DLL_PROCESS_DETACH,系统仍然调用此函数,它首先会调用DllMain,当DllMain返回后,对全局或静态对象进行析构。
    3)对于Dll_THREAD_ATTACH和DLL_THREAD_DETACH而言,一般不做特别处理。
    更详细的内容可以参考核心编程一书。的确,如上面各位所言,不管是EXE或是DLL不需要担心静态成员的初始化,看来是我多虑了,不管如何,我们要感谢c++的运行时,做了蛮多工作。
      

  9.   

    我是在同一个EXE调用同一个DLL里声明了两次,我的程序需要在类里有两个线程,这个类要被声明500多次,单个声明为一个整体,内部要有计算.
      

  10.   

    class mytest{
    private:
        static enum{ARRAY_NUM = 10};
    }
    算吗?