跳转到内容

更多 C++ 习语/通过初始化附加

来自 Wikibooks,开放书籍,开放世界

通过初始化附加

[编辑 | 编辑源代码]

在程序执行开始之前将用户定义的对象附加到框架。

也称为

[编辑 | 编辑源代码]
  • 带有构造函数的静态对象

某些应用程序编程框架,如 GUI 框架(例如 Microsoft MFC)和对象请求代理(例如某些 CORBA 实现)使用自己的内部消息循环(也称为事件循环)来控制整个应用程序。应用程序程序员可能或可能没有自由编写应用程序级 main 函数。通常,main 函数被埋藏在应用程序框架的深处(例如,MFC 中的 AfxWinMain)。无法访问 main 使程序员无法在主事件循环开始之前编写应用程序特定的初始化代码。通过初始化附加习语是一种在框架控制的循环开始执行之前执行应用程序特定代码的方法。

解决方案和示例代码

[编辑 | 编辑源代码]

在 C++ 中,全局对象和全局命名空间中的静态对象在 main 开始之前初始化。这些对象也称为静态存储持续时间的对象。静态存储持续时间的对象的这一属性可用于将对象附加到系统,如果程序员不允许编写自己的 main 函数。例如,考虑以下使用 Microsoft Foundation Classes (MFC) 的(最小可能)示例

///// File = Hello.h
class HelloApp: public CWinApp
{
public:
  virtual BOOL InitInstance ();
};
///// File = Hello.cpp

#include <afxwin.h>
#include "Hello.h"
HelloApp myApp; // Global "application" object
BOOL HelloApp::InitInstance ()
{
 m_pMainWnd = new CFrameWnd();
 m_pMainWnd->Create(0,"Hello, World!!");
 m_pMainWnd->ShowWindow(SW_SHOW);
 return TRUE;
}

上面的示例创建了一个标题为“Hello, World!” 的窗口,仅此而已。这里要注意的关键是 HelloApp 类型的全局对象 myAppmyApp 对象在 main 执行之前被默认初始化。作为初始化对象的副作用,CWinApp 的构造函数也被调用。CWinApp 类是框架的一部分,并调用框架中其他几个类的构造函数。在这些构造函数的执行过程中,全局对象被附加到框架。该对象后来被 AfxWinMain 检索,它是常规 main 的 MFC 等效项。HelloApp::InitInstance 成员函数仅为完整起见而显示,不是该习语的必要组成部分。此函数在 AfxWinMain 开始执行后调用。

全局和静态对象可以通过几种方式初始化:默认构造函数、带参数的构造函数、从函数的返回值赋值、动态初始化等。

注意事项

在 C++ 中,同一个编译单元中的对象按定义顺序创建。但是,跨不同编译单元的静态存储持续时间对象的初始化顺序没有明确定义。命名空间中的对象在访问该命名空间中的任何函数/变量之前创建。这可能或可能不在 main 之前。销毁顺序与初始化顺序相反,但初始化顺序本身没有标准化。由于这种未定义的行为,当静态对象的构造函数使用尚未初始化的另一个静态对象时,会发生静态初始化顺序问题。这种习语很容易陷入这个陷阱,因为它依赖于静态存储持续时间的对象。

已知用途

[编辑 | 编辑源代码]
[编辑 | 编辑源代码]

参考资料

[编辑 | 编辑源代码]
  • "通过初始化附加习语的改进可移植性的 C++ 语言扩展建议".
华夏公益教科书