今天拍代码,拍着拍着,一不小心就撞上了静态初始化的相依性问题。
静态初始化的相依性问题是一个全局对象还未被初始化,就在另外一个文件中被使用。
产生静态初始化的相依性问题的原因是,连接器进行连接时指定的文件初始化顺序和程序员期望的顺序不一致。
一开始还没意识到是由于相依性造成的错误,只是弹出个对话框说afx.inl文件的133行断言失败。其实这个断言失败前两天已经碰到过,也是晚上加班的时候。那次是因为对静态成员的初始化方法不正确。搜搜google,再翻翻TICPP,就解决了这个问题。但这次又冒出来相同的断言失败。显然实现上还有隐藏颇深且未发现的BUG。
通过查看日至,发现是VISY-Quick通信协议类的一个类型为CString的静态成员变量未被初始化(即没有分配内存空间,这时候CString仍然指向NULL),油品类就开始想往这个静态成员变量内赋值了。
这时才想起来看TICPP的时候,看到有一章节就专门介绍如何处理静态初始化的相依性。而且还提供了两种解决方法。这个周末抽空看一下,争取周一能把这个相依性问题给解决了。
今天仔细看了一下TICPP中Eckel给出的第二种解决静态初始化的依赖性问题的解决方法。
这个方法所依据的是函数内部定义的静态对象在函数第一次被调用时初始化,且只被调用一次。依据这点,我们就能把一个静态对象放在一个能够返回对象引用的函数中。有谁想访问这个静态对象,那它必须来调用这个函数来获得静态对象。这样就能确保静态变量先被初始化,再被使用。
看了书中的例子,又想了一下自己的应用。一方面觉得两边有不小的区别,另一方面,自己的应用也比书中的离子复杂不少。最后,还是不敢在工程中贸然使用这个方法。等做了TICPP的习题后,深入理解了Eckel的思想精髓,再来使用。
最后还是用了一种笨办法,在对访问静态对象的类之前,对包含静态对象的类创建实例,进行初始化。
本来这个包含静态对象的类是负责进行通信协议的解析和生成应答,类里面不是静态成员变量,就是静态成员函数,所以,原来使用这个类是不需要创建实例的。