C++静态初始化遇到问题!请高手解答.[100分]

良少
博客专家认证
2006-06-22 03:34:37
C++静态初始化遇到问题!请高手解答.

我们知道,C++的初始化,是先执行类的静态成员变量的赋值,然后,再执行实例化:实例变量的赋值和构造函数的代码。
现在,我写的一个类,它的实例变量和静态变量,调用的赋值语句,都是该类的一个静态方法。并且,这个方法的参数,是一个变量,而不是一个指针。
由于,我不能够在调用方法时,在实参中定义一个变量,所以,我为了执行赋值,必须要执行两条语句:
1,建立一个临时变量,用作实参。
2,实例变量赋值,或者静态变量赋值。

对于实例变量的赋值来说,我可以在构造函数中执行。这样,我写多行代码是没问题的。
现在的问题是,静态变量的赋值。在C++中,静态变量的赋值,只能够是一条语句。这就出现了问题!

当然,对这个问题,也有解决的办法。比如说,另外写一个方法,包装原来的方法,或者再写一个静态方法。但是,这样解决问题,不是很好。

请问,C++中有没有静态初始化的语句块。 这种情况,最优的解决方案是什么。


...全文
802 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
勉励前行 2006-06-23
  • 打赏
  • 举报
回复
#pragma startup
这是C时代的产物,C++时代没有抛弃它而已. 至于编译器的兼容性,应该大部分都兼容吧.毕竟是C语言开始就支持的东西.

用另外一个类,是为了封装上的问题,用静态函数方法时,该方法要被声明为public ,误用就麻烦了. 而另外写一个初始化类,该类放在Cpp文件中,对外是不可见的,所声明的全部变量对外也是不可见的,也就没有全部变量所带来的其他问题.(但有全局变量重名问题,如果重名,编译器会因此警告)

良少 2006-06-23
  • 打赏
  • 举报
回复
我看还是不要使用全局变量和函数的机制吧。这样太危险了。
不如使用类的静态函数,封装在类里,这样保险些。
sarh2os 2006-06-23
  • 打赏
  • 举报
回复
#pragma startup MyStartFun
#pragma exit MyExitFun
顺便问楼上一句,这两条预编一命令,大多数编译器都支持么?
良少 2006-06-23
  • 打赏
  • 举报
回复
楼上的,你的意思是,另外写一个类,然后在该类的构造函数中写上初始化代码。

在X类中,静态实例变量是该类的一个实例。
这样,初始化X类时,只会执行一次实例化该类。这样,构造函数内的代码就只被执行一次。
并且,可以写多行代码来执行初始化。

这个办法不错,但是有点绕。 和重载方法比起来差不多。

那么,各位C++的老鸟。 看来在C++中是没有static{...}静态初始化块和{ }初始化块这样的机制的了?



sarh2os 2006-06-23
  • 打赏
  • 举报
回复
呵呵,楼上说的好!
用你的InitClass,配合我的上面给出的InitStaticAll函数,就可以很方便的初始化类的静态成员了。呵呵:)
勉励前行 2006-06-23
  • 打赏
  • 举报
回复
对于需要针对某个类的全局初始化代码,则可以定义一个全局变量来做
头文件:
class X{...};
CPP文件
class MyInitClassX
{
public: MyInitClassX(){ /*这里写上初始化代码*/ }
};
static MyInitClassX InitClassX ; //这是一个空对象,不会多占空间
//定义一个全局变量,则会执行初始化代码.先于在该头文件定义的每个对象而执行.只执行一次
勉励前行 2006-06-23
  • 打赏
  • 举报
回复
全局静态变量会先于程序而初始化.
int X::staticI = X::print(new string("X的静态变量初始化"));
//上面这种方式不知可否?而且有new 没有delete
如果要控制初始化次序.则要注意先后次序. 多个单元定义的全局静态变量其先后次序未定(编译器相关).
要写几行代码,也可在startup 与exit这两个函数中写上初始化代码,从而控制初始化过程.
#pragma startup MyStartFun
#pragma exit MyExitFun
int X::staticI ; //为静态变量分配空间.
X *abc ;
void MyStartFun(void)
{
//初始化代码.只是例子
string *A = new string("X的静态变量初始化");
X::staticI = X::print(A);
delete A ;
abc = new X;
}
void MyExitFun(void)
{
//结束时代码
delete abc ;
}
这些代码会在 main 函数前(MyStartFun)或后(MyExitFun)执行.如果是代码块(DLL)则在dll初始化及退出时执行.
sarh2os 2006-06-23
  • 打赏
  • 举报
回复
C++有缺点,也有优点。就如Java有缺点,也有优点。但是,Java是一种现代的语言。之所以说它现代,是因为Java委员会和社区在不断的改进Java,吸收了很多先进的技术,也去掉了不少落后和错误的特性。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
特性最差的语言是汇编语言,或者说是机器语言。但是我们不得不用它。在某些情况下他们是最好的选择。

而C++被AT&T的委员会严格的控制着,外界的编程高手难以对它施加影响。而且,其管理人员固执,因循守旧。
总之,C++固步自封,改进太慢,太封闭。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
改进太慢?你是说把C++改成java么?C++新的标准要出来了,应该会有很多新的特性,但是它永远不会变成java。在C++的指导思想里:与C的兼容和效率最大化是第一准则。或许增加一个static{}块应该不是难事吧,前提是它不影响效率。

推荐楼主看看ARM这样的书,看完之后你就不会用现在的心情面对C++了。C++中任何一个细节都是有原因的。而且C++真的不能算改进缓慢的语言,很多“好的特性”它不是不愿意加进去,而是如果那么做有悖于它的原则。
对于楼主而言,如果想找和C++很像又具备java良好特性的语言,C#是个不错的选择。当然前提是必须在Windows下开发。
良少 2006-06-23
  • 打赏
  • 举报
回复
楼上说得对! 我也是这个意思。 语言,只是我们吃饭的家伙。

我只是不太熟悉C++的语法机制,来这里问问,没有贬低C++的意思。不过,我确实觉得C++发展太缓慢,太封闭了。98年标准化至今,没有改变过。
langzi8818 2006-06-23
  • 打赏
  • 举报
回复
每个事物都有他自身的规则,优点和缺点。去遵守就好了。

JAVA还不用你去管理内存的,的确很方便
良少 2006-06-22
  • 打赏
  • 举报
回复
static{}块 里写的代码,会在类初始化时被执行。 这里可以使用所有非本对象的实例方法。

而对于这个需求,我认为是非常合理的。 我对C++并不熟悉,不知道C++有没有类似的机制。

还有,我并不是想到C++这里来教训C+社区的程序员。老实说,我并不喜欢C++。但是,我学习C++也不是为了贬低C++。
由于我的接下来的工作需要使用C++,所以我需要学习C++。
C++有缺点,也有优点。就如Java有缺点,也有优点。但是,Java是一种现代的语言。之所以说它现代,是因为Java委员会和社区在不断的改进Java,吸收了很多先进的技术,也去掉了不少落后和错误的特性。
而C++被AT&T的委员会严格的控制着,外界的编程高手难以对它施加影响。而且,其管理人员固执,因循守旧。
总之,C++固步自封,改进太慢,太封闭。
但是,我还是不得不学习C++。对我来说,C++也并非无法接受。

我知道,绝大部分的程序员,都对语言和某些大师有崇拜的情结。希望我的上述言论不会使你感到不快!
谢谢!

sarh2os 2006-06-22
  • 打赏
  • 举报
回复
在java里的static{}块对static member的初始化好像也没有说一个静态变量可以写几行代码初始化吧?我对java略有涉猎,没有深究,所以这么说可能不对。
但有一点可以确定,那就是不采用我告诉你的方法,你无法保证non-local-static member的初始化顺序。这个结论是Scott Meyers下的。我只是遵从权威而以。
看了LZ的贴子我越来越糊涂。我开始以为你是想寻求一个初始化static member的合理方法。可是现在我觉得,你是在向所有的C++用户宣称,你发现了一个新大陆:原来C++初始化静态变量是这么的不方便!
是的,C++不方便的地方有很多。我可以很明确的告诉你,正如你所说在C++中没有如java一样方便的静态变量初始化方法。但是这有什么什么关系呢?既然要用它我们就要接受这些。如果LZ不能忍受C++给你带来的“极大”不便,大可放弃使用。java也是很好的语言。如果想找比java还“方便”的,python也很好:)
sinall 2006-06-22
  • 打赏
  • 举报
回复
就是C++的静态变量初始化,我不能写几行代码,这就很不方便。
——————————————————————————————————————————

class A
{
public :
A(int a, char b) { }
};

static A a(1, 'c');
sinall 2006-06-22
  • 打赏
  • 举报
回复
太费劲了,就不能简单描述一下问题吗?-_-|||
良少 2006-06-22
  • 打赏
  • 举报
回复
我这里的print这个函数,只是一个说明问题的例子。 仅仅解决这个问题,是不够的。我希望的是能够简洁的解决同类问题。

静态变量的初始化代码,应该只被执行一次。

另外,对于string对象的释放,我也完全可以在函数体内delete s;
这些都不是问题的关键。

这里的关键一点,就是C++的静态变量初始化,我不能写几行代码,这就很不方便。
sarh2os 2006-06-22
  • 打赏
  • 举报
回复
当然,尽量还是不要定义全局变量。我基本明白你的意思了。
我觉得你不用重载
static int print(shared_ptr<string> s);//string对象引用
下面这句也应该可以运行
int X::staticI=X::print(new string("X的静态变量初始化"));
我对boost不很了解。如果boost::shared_ptr的单参数构造函数不是声明为explicit。上面的代码应该没问题。
sarh2os 2006-06-22
  • 打赏
  • 举报
回复
如果不用string指针,只是用string对象不就好了。print生命周期结束,string自动解析。如果要用shared_ptr<string>也不是不可以。在C++中是可以定义全局变量的。在cpp作如下定义:
shared_ptr<string> s = new string("ssss");
搞定!
sarh2os 2006-06-22
  • 打赏
  • 举报
回复
这还不简单吧InitStackAll函数放到构造函数里不久好了。
唯一的不好的就是每次都要生成三个临时引用,指向三个静态变量。
但是InitStackAll执行完就消失了。而且InitStackAll是inline,执行效率不会因为频繁调用而降低。
良少 2006-06-22
  • 打赏
  • 举报
回复
static int print(shared_ptr<string> s);//string对象引用
static int print(string* s);//栈里产生的一般string

这是2个静态方法。 本来,我只需要使用
static int print(shared_ptr<string> s);
这个方法。这个方法的参数,使用了智能指针,可以自动回收string。

但是,由于在静态变量的赋值过程中,只能够在一行中执行。
而我必须要使用一个临时变量,这个临时变量无法在参数调用时给出,
所以,我只有重载了print方法,提供了
static int print(string* s);这个方法。
现在的调用代码是:
int X::staticI=X::print(new string("X的静态变量初始化"));
但是,不使用shared_ptr对象,我就必须要自己删除string对象了!
这是我不愿意看到的!

良少 2006-06-22
  • 打赏
  • 举报
回复
但是,在对象初始化的过程中,static方法并不会被自动执行。
初始化的顺序是这样的:
1,基类到子类,依次执行静态变量的初始化。
2,基类到子类,依次执行对象的实例化: 先执行实例变量的赋值,然后是构造函数中代码的执行。

而你上面的静态方法,并不会在对象初始化的过程中得到执行。
加载更多回复(2)

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧