构造函数的职责 -- 关于全局变量的构造函数里执行太多复杂操作导致的问题

最近碰到几起,因为在构造函数里执行了较多的复杂的操作(比如,读写文件,创建进程,初始化gdi+,等等)导致发布出去的dll在使用时遇到很多麻烦。

举例1:
tsGUI的全局变量的构造函数里面 初始化 GDI+, StereoCamera.dll依赖了tsGUI, xeyezHal.dll依赖了StereoCamera.dll,
这导致发布出去的xeyezHal.dll给识别器引擎安装包带来了隐患:

安装包卸载时,需要调用 xeyezHal.dll中的一个接口, 虽然该接口很简单,并且接口实现和StereoCamera无关,但加载xeyezHal.dll接口时需要事先加载StereoCamera.dll, 也就需要加载tsGUI.dll, 加载dll之前又必须首先初始化dll中的全局变量, 因而导致StereoCamera.dll内全局变量的初始化,也导致tsGUI的全局变量的初始化,进一步导致初始化GDI+。

好了,问题出现了,StereoCamera.dll的全局变量在初始化的时候,初始化了很多组件:比如 new Classifier, 该Classifier的构造函数里面又初始化了一大堆东西。。。这里涉及到了 读取SVM训练文件操作, 由于工作路径不对,导致加载文件失败,进而导致识别器引擎安装包退出!

tsGUI的全局变量在初始化的时候初始化了GDI+, 而msdn上说对gdi+的初始化有限制,这导致识别器引擎安装包失去响应!

举例2:
http://blog.csdn.net/zdl1016/archive/2009/07/18/4360424.aspx
一个线程被另一个不相干的线程卡住了 - 不良的使用全局变量的构造函数的习惯

把setupMonitor(),installKb()等代码放在主线程中别的地方执行

正确的编码规范:
Google C++ Style Google开源项目的编码风格,代码风格
参考:http://www.cnblogs.com/kaiyang/archive/2008/10/07/1305475.html

1. 构造函数(Constructor)的职责

构造函数中只进行那些没有实际意义的(trivial,译者注:简单初始化对于程序执行没有实际的逻辑意义,因为成员变量的有意义的值大多不在构造函数中确定)初始化,可能的话,使用Init()方法集中初始化为有意义的(non-trivial数据。

定义:在构造函数中执行初始化操作。

优点:排版方便,无需担心类是否初始化。

缺点:在构造函数中执行操作引起的问题有:

1) 构造函数中不易报告错误,不能使用异常。

2) 操作失败会造成对象初始化失败,引起不确定状态。

3) 构造函数内调用虚函数,调用不会派发到子类实现中,即使当前没有子类化实现,将来仍是隐患。

4) 如果有人创建该类型的全局变量(虽然违背了上节提到的规则),构造函数将在main()之前被调用,有可能破坏构造函数中暗含的假设条件。例如,gflags尚未初始化。

结论:如果对象需要有意义的(non-trivial初始化,考虑使用另外的Init()方法并(或)增加一个成员标记用于指示对象是否已经初始化成功。

你可能感兴趣的:(debug)