8.1 How to Derive a Class from CObject

This section describes the minimum steps necessary to derive a class from CObject. Other cookbook sections describe the steps needed to take advantage of specific CObject features, such as serialization and diagnostic debugging support.

In the following discussions, the terms “interface file” and “implementation file” are used frequently. The interface file (often called the header file, or .H file) contains the class declaration and any other information needed to use the class. The implementation file (or .CPP file) contains the code that implements the class member functions. For example, for a class named CPerson, you will typically create an interface file named PERSON.H and an implementation file named PERSON.CPP. For some small classes that will not be shared, it is sometimes easier to combine the interface and implementation into a single .CPP file.

There are three levels of functionality that you can choose from when deriving a class from CObject:

Basic functionality that does not include run-time class information or serialization

Basic functionality plus run-time class information

Basic functionality plus run-time class information plus serialization support

Classes designed for reuse should at least include run-time class support and serialization support if any future serialization need is anticipated.

You choose the level of functionality by using specific declaration and implementation macros in the declaration and implementation of the classes you derive from CObject. The following sections describe how to specify the level of functionality.

·To use basic CObject functionality:

Use the normal C++ syntax to derive your class from CObject (or from a class derived from CObject).

The following example shows the simplest case: the derivation of a class from CObject:

class CPerson : public CObject

{

// add CPerson-specific members and functions...

}

Typically, however, you will want to override some of CObject's member functions to handle the specifics of your new class. For example, you will usually want to override the Dump function of CObject to provide debugging output for the contents of your class. For details on how to override Dump, see page 286. You will also want to override the AssertValid function of CObject. (For a description of how to override AssertValid, see the section on AssertValid on page 289).

·To add run-time class information:

CObject contains support for run-time class information. This means that you can determine the exact class of an object at run-time and also determine the base class from which it was derived. This capability is not supported directly by the C++ language. To take advantage of the run-time class information, you must do the following three steps:

1.Derive your class from CObject, as described in the previous section.

2.Use the DECLARE_DYNAMIC macro in your class declaration, as shown here:

class CPerson : public CObject

{

DECLARE_DYNAMIC( CPerson )

// rest of class declaration follows...

};

3.Use the IMPLEMENT_DYNAMIC macro in the implementation file (.CPP) of your class. This macro takes as arguments the name of the class and the name of its base class, as follows:

IMPLEMENT_DYNAMIC( CPerson, CObject )

Note :

The IMPLEMENT_DYNAMIC macro should be evaluated only one time during a compilation. Do not use IMPLEMENT_DYNAMIC in an interface file (.H) that will be included in more than one file. The best policy is to always put IMPLEMENT_DYNAMIC in the implementation file (.CPP) for your class.

If you use these two macros as described, you can then use the RUNTIME_CLASS macro and IsKindOf member function to determine the class of your objects at run-time. For a description of how to use these features of CObject, see “How to Access Run-Time Class Information” on this page.

·To add serialization support:

Serialization is the process of writing or reading the contents of an object to and from a file. The following five steps are required to support serialization in your classes.

1.Derive your class from CObject.

2.Use the DECLARE_SERIAL macro in the class declaration.

3.Define a constructor with no arguments (a default constructor).

4.Use the IMPLEMENT_SERIAL macro in the class implementation file.

5.Override the Serialize member function.

For more details on how to derive from CObject to enable serialization for your class, see “Serialization” on page 279. Each of the steps listed above is described in that section.

Note :

The serialization features necessarily include the run-time class information features described in the previous section. If you use the DECLARE_SERIAL and IMPLEMENT_SERIAL macros, you do not have to use the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC macros. The run-time class macros are already included in the serialization macros.