More C++ Idioms/Attach by Initialization

Attach by Initialization

edit

Intent

edit

Attach a user-defined object to a framework before program execution begins.

Also Known As

edit
  • Static-object-with-constructor

Motivation

edit

Certain application programming frameworks, such as GUI frameworks (e.g., Microsoft MFC) and object request brokers (e.g., some CORBA implementations) use their own internal message loops (a.k.a. event loops) to control the entire application. Application programmers may or may not have the freedom to write the application-level main function. Often, the main function is buried deep inside the application framework (e.g, AfxWinMain in case of MFC). Lack of access to main keeps programmers from writing application-specific initialization code before the main event loop begins. The attach-by-initialization idiom is a way of executing application-specific code before the execution of a framework-controlled loop begins.

Solution and Sample Code

edit

In C++, global objects and static objects in the global namespace are initialized before main begins. These objects are also known as objects of static storage duration. This property of objects of static storage duration can be used to attach an object to a system if programmers are not allowed to write their own main function. For instance, consider the following (smallest possible) example using 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;
}

The above example creates a window titled "Hello, World!" and nothing more. The key thing to note here is the global object myApp of type HelloApp. The myApp object is default-initialized before the execution of main. As a side-effect of initializing the objects, the constructor of CWinApp is also called. The CWinApp class is a part of the framework and invokes constructors of several other classes in the framework. During the execution of these constructors, the global object is attached to the framework. The object is later on retrieved by AfxWinMain, which is the MFC equivalent of the regular main. The HelloApp::InitInstance member function is shown just for the sake of completeness and is not an integral part of the idiom. This function is called after AfxWinMain begins execution.

Global and static objects can be initialized in several ways: default constructor, constructors with parameters, assignment from a return value of a function, dynamic initialization, etc.

Caveat

In C++, objects in the same compilation unit are created in order of definition. However, the order of initialization of objects of static storage duration across different compilation units is not well defined. Objects in a namespace are created before any function/variable in that namespace is accessed. This may or may not be before main. Order of destruction is the reverse of initialization order but the initialization order itself is not standardized. Because of this undefined behavior, the static initialization order problem comes up when a constructor of a static object uses another static object that has not been initialized yet. This idiom makes it easy to run into this trap because it depends on an object of static storage duration.

Known Uses

edit
edit

References

edit
  • "Proposed C++ language extension to improve portability of the Attach by Initialization idiom".