一种类静态成员初始化的方案,高手可以看看

BlueDog 2009-08-23 10:20:19
众所周知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中,函数体内的静态变量初使化是在什么时候。
...全文
407 16 打赏 收藏 举报
写回复
16 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
xuexuekan 2011-03-17
class mytest{
private:
static enum{ARRAY_NUM = 10};
}
算吗?
  • 打赏
  • 举报
回复
luofeng4213 2009-12-22
我是在同一个EXE调用同一个DLL里声明了两次,我的程序需要在类里有两个线程,这个类要被声明500多次,单个声明为一个整体,内部要有计算.
  • 打赏
  • 举报
回复
luofeng4213 2009-12-22
我遇到了楼主的问题,当从两个地方声明两次类并初始化时,静态变量好像在一段内存,会一起变的
  • 打赏
  • 举报
回复
BlueDog 2009-08-25
总算找到了完整的说明,呵呵
相关资料来自于《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++的运行时,做了蛮多工作。
  • 打赏
  • 举报
回复
BlueDog 2009-08-24
top
  • 打赏
  • 举报
回复
MoXiaoRab 2009-08-24
静态变量在DLL的生存周期开始的第一个使用者
  • 打赏
  • 举报
回复
帮顶学习!
  • 打赏
  • 举报
回复
jyh_baoding 2009-08-24
帮顶一个
  • 打赏
  • 举报
回复
雪影 2009-08-23
2、局部静态变量是非线程安全的,主要是指在初始化时有可能被线程切出去,从而导致多次初始化
局部静态变量是非线程安全的,主要是因为可能被线程随机读写,数据结果的不确定性。而不是初始化问题啊
  • 打赏
  • 举报
回复
BlueDog 2009-08-23
刚翻了翻资料,并写了一点代码测试一下,至少有两点是清晰的

1、函数体内的局部静态变量初始化是第一次调用该函数才进行初始化,
2、局部静态变量是非线程安全的,主要是指在初始化时有可能被线程切出去,从而导致多次初始化

不清楚的是局部静态变量的析构发生在什么时候,由谁来调用析构
资料上是说程序结束时,
是main返回后,由clr来调用析构还是什么的,
在dll在又会是如何的呢?

akirya 你说的类静态变量不要由用户来写初始化,那么我问你
你的类用于 dll中时,类静态成员初始化时机是在什么时候?
  • 打赏
  • 举报
回复
雪影 2009-08-23
没看清楚楼主试图在类定义中初始化静态变量的意图。

在类中定义静态变量,在cpp文件中初始化静态变量,我没有觉得有什么不好的。

如果涉及多线程的话,线程中的类对象的静态变量不是安全的。
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 bluedog 的回复:]
1楼没有明白我的意思呀

我这段演示代码的目的是达到不需要客户程序员去初始化的一个类的静态成员



[/Quote]
你写的类还打算让别人给你写静态成员初始化? 那样不乱套了?

你提出的解决方式没有考虑线程同步。
  • 打赏
  • 举报
回复
oyljerry 2009-08-23
[Quote=引用 3 楼 bluedog 的回复:]
1楼没有明白我的意思呀

我这段演示代码的目的是达到不需要客户程序员去初始化的一个类的静态成员

我们知道在EXE中,类的静态成员初始化是由运行时去完成的,
但是我不是很清楚象函数体内的静态变量初始化时机

它是函数第一次运行时才进行呢,还是由CLR在调用main之前完成

这里面区别很大,因为对于DLL就不存CLR的初始化了!!!



[/Quote]
vc运行时库会在进入main之前进行初始化,所以才要你在cpp中全局初始化
  • 打赏
  • 举报
回复
BlueDog 2009-08-23
1楼没有明白我的意思呀

我这段演示代码的目的是达到不需要客户程序员去初始化的一个类的静态成员

我们知道在EXE中,类的静态成员初始化是由运行时去完成的,
但是我不是很清楚象函数体内的静态变量初始化时机

它是函数第一次运行时才进行呢,还是由CLR在调用main之前完成

这里面区别很大,因为对于DLL就不存CLR的初始化了!!!



  • 打赏
  • 举报
回复
oyljerry 2009-08-23
静态成员变量初始化在dllmain之前,可以提供静态成员函数等来访问,读取静态成员变量
  • 打赏
  • 举报
回复
呃,静态变量最好不要暴露给外界。
可以将静态变量改成类实现cpp的匿名空间的全局变量.

dll中的静态变量初始化在DllMain之前。
  • 打赏
  • 举报
回复
相关推荐
发帖
VC/MFC
加入

1.6w+

社区成员

VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
申请成为版主
帖子事件
创建了帖子
2009-08-23 10:20
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……