This section gives recommendations for designing Open Class Library applications. These general recommendations should not substitute for detailed design guidelines. Many of the topics listed here require a great deal of consideration when you design complex object-oriented applications.
The Hello World sample application shipped with this product uses these design recommendations.
To use the classes, functions and operators available in the IBM Open Class Library, you must include the parts of the library's interface that you need in your C++ source code. To include an interface, you must either:
#include <filename>
where filename is the name of the header file
Then, in the body of your program, you can use a class, function or operator defined in the header file, as well as derive new classes and overload the functions and operators.
Most applications require you to derive new classes from existing classes. You derive new classes to inherit implementation details from a base class.
The following table provides a starting point to determine which base class to use:
Class Functionality | Derived From |
---|---|
Attribute | IAttribute (for window attributes) |
Canvas class | ICanvas |
Control | IWindow or ITextControl |
Cursor | - |
Data type | - |
Dialog window | IFrameWindow |
Event | IEvent |
Primary or secondary window | IFrameWindow |
Settings | - |
Style | IBitFlag |
Window behavior | Handler specific to the window |
Do not derive from a particular base class unless you have a good reason to do so. When creating data type, cursor or settings classes,don't derive from a base class, unless for some reason your new class must derive from one of your own base classes.
For window attributes, derive from IAttribute, since the IWindow interface expects IAttribute objects. For other named attributes, IAttribute is also a handle. For arbitrary, unnamed attributes attached to your own classes, you do not need to derive from an Open Class Library base class.
It is easier to inherit from multiple classes when you design simple applications. Because all of the functions from the derived classes are immediately available, you can easily use them as-is and not override them.
However, as your application evolves into a more complex application, it can be difficult to anticipate how changes in the functions of the inherited classes will affect the derived class.
Generally, if the class you design is-a, for example, frame window, then it should inherit from the IFrameWindow class. Inheriting from IFrameWindow is typical, but not necessary in most cases. For example, has-a is often fine with frame windows. However, if the class has-a, for example, command handler, ICommandHandler should be represented by a member in the derived frame window. It should not inherit from the command handler class. The Hello World version 3 sample application provides an example.
When you override inherited member functions, such as the ICommandHandler::command function, that are defined as virtual, declare the overriding function as virtual too. This improves the readability of the inheriting class by saving the reader from having to search up the inheritance chain to discover that the function was originally defined as virtual.
If you create objects dynamically by using the new operator, delete them by using the delete operator. If an object is composed of dynamically created objects, that is, you create the composed objects with the new operator in the constructor of the composing object, then you should delete the object in the destructor of the composing object.
Note: | An exception to this rule is when you use the autoDelete behavior of IWindow derived classes. Refer to IWindow::setAutoDeleteObject for more information. |
The values of strings in applications vary by user because of preference or national language. Therefore, you should define strings outside the application.
In Windows and OS/2 this capability is provided by using Windows or OS/2 Presentation Manager (PM) resource compiler (.rc) files. This format lets you use descriptive tags to identify tables of strings and associate them with unique IDs in your application. In AIX, the default format used by the resource compiler is the OS/2 format.
The syntax for the resource files on the various platforms are
very similar, but the keywords are different. Also, this
product's resource compiler handles extended menu syntax and
keywords. Refer to the Resource Compiler - Syntax or
Resource Compiler - Syntax
topics for information on the resource file syntax. Refer to the Resource Conversion
Utility topic for information on converting your resource
files.
Hello World versions 1 and 2 show how to use Open Class Library functions to reference strings from resource files.
Use resource files to define menu bars, submenus, menu items, and accelerators. By using the same ID for the menu bar and the frame window, you can define the layout, menu item text, and accelerator key definitions external to application logic. Hello World version 3 and version 4 demonstrate this feature.
Windows and OS/2 PM provide support for dialog templates, which are "layouts" of frame windows and controls. This support is not available in Motif and, therefore, is not portable. Instead, use the canvas classes, such as IMultiCellCanvas and ISetCanvas, for designing portable dialogs across Windows, Motif, and OS/2. Hello World version 4 demonstrates this feature. Note that there are also other features of canvases, such as automatic layout, that compensate for internationalization text changes or font changes.
To specify the client window in a way that is portable, use the IFrameWindow::setClient function.