Provide a Class Identifier for Your Class
Polymorphic persistence lets you save a class in one executable, and restore it in a different executable or in a different run of the original executable. The restoring executable can use the class, without prior knowledge of its type. In order to provide polymorphic persistence, a class must have a unique, unchanging identifier. Because classes derived from RWCollectable are polymorphically persistent, they must have such an identifier.
Identifiers can be either numbers or strings. A numeric identifier is an unsigned short with a typedef of RWClassID. A string identifier has a typedef of RWStringID. If you choose to specify a numeric identifier, your class will have an automatically generated string identifier, which will be the same sequence of characters as the name of the class. Similarly, if you choose to specify a string identifier, your class will have an automatically generated numeric ID when used in an executable.
The Essential Tools Module includes two definition macros to provide an identifier for the class you design. If you want to specify a numeric ID, use:
 
RW_DEFINE_COLLECTABLE_CLASS_BY_ID (USER_MODULE, className, numericID)
If you want to specify a string ID, use:
 
RW_DEFINE_COLLECTABLE_CLASS_BY_NAME (USER_MODULE, className, stringID)
Note that you do not include the definition macros in the header file for the class. Rather, the macros are part of a .cpp file that uses the class. You must include exactly one define macro for each RWCollectable class that you're creating, in one and only source file (.cpp). Use the class name as the first argument, and a numeric class ID or string class ID as the second argument. For the bus example, you can include the following definition macros:
 
RW_DEFINE_COLLECTABLE_CLASS_BY_ID(USER_MODULE, Bus, 200)
or:
RW_DEFINE_COLLECTABLE_CLASS_BY_NAME(USER_MODULE, Client, "a client")
The first use provides a numeric ID 200 for class Bus, and the second provides a string ID, “a client”, for class Client.
In the remainder of this manual, we use RWDEFINITION_MACRO to indicate that you can choose either of these macros. In example code, we will pick one or the other macro.
Either macro will automatically supply the definitions for the virtual functions isA() and newSpecies(). In Virtual Function isA() through A Note on the RWFactory, we describe these virtual functions, discuss the stringID() method and provide a brief introduction to the RWFactory class, which helps implement polymorphic persistence.
The RWDEFINITION_MACROs do more than merely implement the two mentioned methods. Before you choose not to use one of the provided macros, review them in detail to be sure you understand all that they do.