Implementing initializers

When new initializers are introduced by a class, as in the preceding examples, the implementation template file generated by the SOM Toolkit C and C++ emitters automatically contains an appropriate stub procedure for each initializer method, for the class implementor's use. The body of an initializer stub procedure consists of two main sections:

In the first section, by default, the parents of the new class are the ancestors whose initializers are called. When something else is desired, the IDL directinitclasses modifier can be used to explicitly designate the ancestors whose initializer methods should be invoked by a new class's initializers.

Important: Under no circumstances can the number or the ordering of ancestor initializer calls in the first section of an initializer stub procedure be changed. The control masks used by initializers are based on these orderings. (If you want to change the number or ordering of ancestor initializer calls, you must use the directinitclasses modifier.) The ancestor initializer calls themselves can be modified as described below.

Each call to an ancestor initializer is made using a special macro (much like a parent call) that is defined for this purpose within the implementation bindings. These macros are defined for all possible ancestor initialization calls. Initially, an initializer stub procedure invokes the default ancestor initializers provided by somDefaultInit. However, a class implementor can replace any of these calls with a different initializer call, as long as it calls the same ancestor (see the example in the next topic). Non-default initializer calls generally take other arguments in addition to the control argument.

In the second section of an initializer stub procedure, the programmer provides any class-specific code that may be needed for initialization. For example, the "Example2_withName" stub procedure is shown below. As with all stub procedures produced by the SOMobjects implementation-template emitters, this code requires no modification to run correctly.

SOM_Scope void SOMLINK Example2_withName(Example2 *somSelf,                                         Environment *ev,
                                         somInitCtrl* ctrl,
                                         string name)
{
    Example2Data *somThis; /* set by BeginInitializer */
    somInitCtrl globalCtrl;
    somBooleanVector myMask;
    Example2MethodDebug("Example2","withName");

    /*
     * first section -- calls to ancestor initializers
     */
     Example2_BeginInitializer_Example2_withName;
     Example2_Init_Example1_somDefaultInit(somSelf, ctrl);

    /*
     * second section -- local Example2 initialization code
     */
}

In this example, notice that the "Example2_withName" initializer is an IDL callstyle method, so it receives an Environment argument. In contrast, somDefaultInit is introduced by the SOMObject class (so it has an OIDL callstyle initializer, without an environment).

Important: If a class is defined where multiple initializers have exactly the same signature, then the C++ usage bindings will not be able to differentiate among them. That is, if there are multiple initializers defined with environment and long arguments, for example, then C++ clients would not be able to make a call using only the class name and arguments, such as:

new Example2(env, 123);

Rather, C++ users would be forced to first invoke the somNewNoInit method on the class to create an uninitialized object, and then separately invoke the desired initializer method on the object. This call would pass a zero for the control argument, in addition to passing values for the other arguments. For further discussion of client usage, see "Using initializers when creating new objects" later in this chapter.


[Back: Considerations re: 'somInit' initialization from earlier SOM releases]
[Next: Selecting non-default ancestor initializer calls]