Essential Tools Module User's Guide : Chapter 6 Collection Classes : Creating an RWCollectable Object : Add RW_DECLARE_COLLECTABLE_CLASS() to your Class Declaration
Add RW_DECLARE_COLLECTABLE_CLASS() to your Class Declaration
The example in “Bus Example Code” includes the macro invocation RW_DECLARE_COLLECTABLE_CLASS(USER_MODULE, Bus) in the declaration for Bus. You must put this macro in your class declaration, using the class name as the argument. Using the macro guarantees that all necessary member functions are declared correctly.
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.
Virtual Function isA()
The virtual function isA() returns a class identifier: a unique number that identifies an object's class. It can be used to determine the class to which an object belongs. Here's the function declaration provided by macro RW_DECLARE_COLLECTABLE_CLASS:
 
virtual RWClassID isA() const;
RWClassID is actually a typedef to an unsigned short. Numbers from 0x8000 (hex) and up are reserved for use by Rogue Wave. You may choose a numeric class ID from 0x0001 to 0x7fff. There is a set of class symbols defined in <rw/tooldefs.h> for the Essential Tools Module. Generally, these follow the pattern of a double underscore followed by the class name with all letters in upper case. For example:
 
RWCollectableString yogi;
yogi.isA() == __RWCOLLECTABLESTRING; // Evaluates true
The macro RW_DECLARE_COLLECTABLE_CLASS(USER_MODULE, className) will automatically provide a declaration for isA(). Either RWDEFINITION_MACRO will supply the definition.
Virtual Function newSpecies()
The job of this function is to return a pointer to a brand new object of the same type as self. Here is the function declaration provided by macro RW_DECLARE_COLLECTABLE_CLASS:
 
virtual RWCollectable* newSpecies() const;
The definition is automatically provided by either version of RWDEFINITION_MACRO.
Function stringID()
The stringID() function acts like a virtual function, but it is not. It returns an instance of RWStringID, a unique string that identifies an object's class. RWStringID is derived from class RWCString. By default, the string identifier for a class is the same as the name of the class. RWStringID can be used instead of, or as a supplement to, RWClassIDs.