Vault  4.1
Public Member Functions | Static Public Member Functions
VClassRegistry Class Reference

VClassRegistry provides a mechanism for instantiating objects dynamically at runtime based on class IDs. More...

#include <vclassregistry.h>

List of all members.

Public Member Functions

 VClassRegistry ()
 Constructs the registry.
virtual ~VClassRegistry ()
 Destructor.
void * instantiateObject (const VString &classID) const
 Instantiates and returns an object of the correct type for the specified class ID.
void registerClass (const VClassFactory *factory)
 Registers a class factory.
const VClassFactoryfindClassFactory (const VString &classID) const
 Returns the class factory for a specified class ID.

Static Public Member Functions

static VClassRegistryregistry ()
 Returns a pointer to the global class registry object.

Detailed Description

VClassRegistry provides a mechanism for instantiating objects dynamically at runtime based on class IDs.

This allows you to write code that obtains a class "ID" and then calls the registry to instantiate the corresponding type of object. You decide what an ID is (it's just a string, so the simple thing is to use the class name as the ID, perhaps qualified with something akin to a Java package name to ensure uniqueness across a global name space), and provide the factory function.

If you prefer, you can create multiple registries and register your class factories with them as you see fit. However, the easiest way to use the registry is to just use the singleton that it creates automatically.

To do this, all you need to do is define a class factory for each registered class. Two macros are provide to make this trivial to add in a consistent fashion. Suppose you have class Foo for which you want a factory registered with the global registry:

In foo.h:

class Foo { .... };

DEFINE_CLASSFACTORY(Foo);

In foo.cpp:

DECLARE_CLASSFACTORY(Foo);

When you need a Foo object but don't know the actual type until runtime (let's say the string name is given to you during some kind of deserialization process where everything is a subclass of Foo, and all of the Foo subclasses also have class factory macros) you just do this:

Foo* aFoo = (Foo*) VClassRegistry::registry()->instantiateObject(name);

The purpose of the above is to create a single FooFactory as a static class variable, which will be created automatically at program startup, that when constructed registers itself with the global registry. This means that you don't have to explicitly register all your classes at some central location in your code; it's almost automatic just by defining the factory that it will get registered.

The method VClassRegistry::registry() is provided to ensure that when the first attempt is made to register a class -- which will presumably be at static initialization time -- the global registry will get created exactly once, before it is actually accessed. This is because the order of static initialization is not guaranteed, and we don't want to clutter the caller's code with checks for the global variable being non-NULL. This is both cleaner and fool-proof.

If you want a separate registry for a set of classes, just create your own separate VClassFactory object, and an accessor function that makes sure it's created upon first use, just like VClassRegistry::registry(). In other words, define your own "myRegistry()" function that looks exactly like the code in VClassRegistry::registry() but uses your own registry global rather than VClassRegistry::gRegistry.

In the class declaration of the class that will own your registry:

public: static VClassRegistry* myRegistry(); protected: static VClassRegistry* gRegistry;

In the class implementation:

static VClassRegistry* ThingThatOwnsMyRegistry::gRegistry = NULL;

static VClassRegistry* ThingThatOwnsMyRegistry::registry() { We're using the "create on first use" idiom here. if (gRegistry == NULL) gRegistry = new VClassRegistry();

return gRegistry; }

Then your FooFactory would only have to change its constructor from the above example to:

FooFactory(const VString& classID) : VClassFactory(classID) { ThingThatOwnsMyRegistry::registry()->registerClass(this); }

Definition at line 109 of file vclassregistry.h.


Member Function Documentation

void * VClassRegistry::instantiateObject ( const VString classID) const

Instantiates and returns an object of the correct type for the specified class ID.

Throws an exception if there is no factory registered for that class ID. The return type is void* because only the factory function knows the actual type; the caller also needs to know something such as the base class, or use RTTI in some fashion, to get the correct type.

Parameters:
classIDthe class ID of the class to be instantiated
Returns:
the newly instantiated object

Definition at line 59 of file vclassregistry.cpp.

References findClassFactory(), and VClassFactory::instantiateObject().

void VClassRegistry::registerClass ( const VClassFactory factory)

Registers a class factory.

Parameters:
factorythe factory for creating some class

Definition at line 65 of file vclassregistry.cpp.

const VClassFactory * VClassRegistry::findClassFactory ( const VString classID) const

Returns the class factory for a specified class ID.

Useful if you can optimize performance by getting the factory once and using it to create many objects, rather than looking it up each time. Throws an exception if there is no factory registered for that class ID.

Parameters:
classIDthe class ID of the class whose factory is to be found
Returns:
the factory for the specified class ID

Definition at line 69 of file vclassregistry.cpp.

References VString::chars().


The documentation for this class was generated from the following files:

Copyright ©1997-2014 Trygve Isaacson. All rights reserved. This documentation was generated with Doxygen.