calling cunstroctor from CString object

M

muley.rahul

Hi
can i call a constructor of a class, if the name is stored in a CString
Object
e.g.

class CBaseClass
{
int x;
};

class CDerClass1: public CBaseClass
{
int y;
};

class CDerClass2: public CBaseClass
{
int z;
};

CString strClassName;
// = L"CMyClass";//using unicode charset....

//main1//i know this


CBaseClass* pPtr;
------
----
----------

if(some condition)
{
strClassName = L"CDerClass1"
pPtr = new CDerClass1;
}
else
{
strClassName = L"CDerClass2"
pPtr = new CDerClass2;
}
//for 2 classes this approach is fine but
//what if i have more than 100 classes derived from the same class
//n at runtime i want to allocate the memory for them.....

//main2//can it be done????


CBaseClass* pPtr;
------
----
----------

if(some condition)
{
strClassName = L"CDerClass1"
}
else
{
strClassName = L"CDerClass2"
}
//now i want to allocate the memory for the class whose name is stored
in the strClassName
pPtr = new "some way to call the constructor whose name is stored in
string.....";


plz help me i m tired of writting this if else statements........
 
T

Tamas Demjen

Hi
can i call a constructor of a class, if the name is stored in a CString
Object
e.g.

I think what you're asking is called a factory. You have to add a thin
infrastructure to your classes. First you need a function that creates a
particular instance, which I will call FactoryCreator:

typedef CBaseClass* (*FactoryCreatorPtr)();

You have to implement this function for each actual class in your hierarchy:

CBaseClass* CDerClass1Creator() { return new CDerClass1; }
CBaseClass* CDerClass2Creator() { return new CDerClass2; }

Then you have to implement a registry, where you will associate class
names with FactoryCreatorPtr pointers. For this purpose I'm going to use
an STL map:

typedef std::map<std::string, FactoryCreatorPtr> FactoryRegistryMap;
FactoryRegistryMap registry;

You have to dynamically register every creator that you want to support:

registry["CDerClass1"] = CDerClass1Creator;
registry["CDerClass2"] = CDerClass2Creator;

The registration doesn't need to be centralized. The only requirement is
that it gets done before you actually create instances.

Now you're ready to create an instance by name:

CBaseClass* CreateClassByName(const FactoryRegistryMap& registry, const
std::string& classname)
{
FactoryRegistryMap::const_iterator found = registry.find(classname);
return (found == registry.end()) ? 0 : (found->second)();
}

If you call this with an unknown name, the function will return 0. If
the classname is already registered, CreateClassByName creates a new
instance, which you're ready to use:

CBaseClass* instance = CreateClassByName("CDerClass1");
instance->[...];
delete instance;

I hope this gets you started.

You can make each class auto-register itself using the following scheme
(put this in each class' .cpp file):

static bool AutoRegister()
{
registry["CDerClass1"] = CDerClass1Creator;
return true;
}
static bool auto_register = AutoRegister();

This way you just need to add the .cpp/.obj/.lib to any of your
projects, and it will auto register with your factory infrastructure,
without having to worry about manual registration. Just make sure there
is only one registry in your entire project (preferably a singleton object).

I recommend that you google for the factory pattern, and you'll find
several alternative implementations.

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top