If I have a base class:
class Base
{
public:
virtual void Test()=0;
};
and, in a dynamically loaded module (.so/.dll), I implemented a class derived from this:
class SomethingFromBase : Base
{
...
};
and, the user, once this library is loaded, asks to create an instance of SomethingFromBase
(let's say we get the name from cin.), and, we have no knowledge of SomethingFromBase
(i.e, no way to just do if(inputstr == "SomethingFrombase") { ... }
is there any way to create an instance of SomethingFromBase?
I'm fairly certain this is impossible in (standard) C++, but, I'm always hoping SO will surprise me!
If this is possible with the addition of some library, I'd still like to know about it.
Thanks!
Edit: See cdhowie's answer. Guides to implementing this technique:
http://www.linuxjournal.com/article/3687?page=0,1
http://www.abstraction.net/ViewArticle.aspx?articleID=67
You typically achieve this by required that plugin libraries define some global variable of a struct type that contains pointers to various functions you can call. (Like setup, teardown, etc.) During the setup function, they would call back into your application to some "register" function where they could pass in a string representing the name of the class, and a factory function pointer that will create an instance when executed.
You stash this away in some map, and when the user enters a string, you look at the map to see if there is a factory function registered. If so, just call it.
So this is not "true" reflection, but you can manually hack it to some degree. See, for example, Pidgin, which allows the specification of protocol plugins that may supply many entries in the protocol list.
EDIT: Here is a nifty guide to implementing something similar. I'm more of a C person, so I can't vouch for it being truly awesome or anything, but at first glance it looks good. I've done similar stuff in C on Linux, and the basic approach works pretty well.
Have a map store the objects of the class, keyed by the class name.
All the classes that need to be created this way, need to be derived from some base class named something like "Creatable"
The code to add the object of the class need to be given with the implementation of class.
//Creatable.h
#define IMPLEMENT_CREATABLE( ClassName ) \
ObjectMap::Instance().Add( string(ClassName), new ClassName );
//ObjectMap.h. This is a singleton
class ObjectMap
{
...........
map<string, Creatable *> myMap;
...........
public:
void Add( const string &className, Creatable * );
Creatable * Get( const string &className );
};
//My Class.h
class MyClass : public Creatable
{
................
};
//My Class.cpp
IMPLEMENT_CREATABLE(MyClass);
//Client.cpp
string className;
cin>>className;
Creatable *anObject = ObjectMap::Instance().Get( className );