Sure, but not the way you would like. C++ has no reflection, so you have to build the mechanism yourself: (See below for EDIT which implements a map of factory pointers)
#include <string>
#include <vector>
#include <memory>
using namespace std;
class Base
{
};
class Dog : public Base
{
};
class Cat : public Base
{
};
int main()
{
typedef vector<string> strings;
strings names;
names.push_back("Dog");
names.push_back("Cat");
names.push_back("Dog");
names.push_back("Cat");
typedef vector<Base*> Bases;
Bases my_objs;
for( strings::const_iterator it = names.begin(), it_end = names.end(); it != it_end; ++it )
{
if( *it == "Dog" )
my_objs.push_back(new Dog);
else if( *it == "Cat" )
my_objs.push_back(new Cat);
}
}
EDIT:
Any solution you come up with in C++ is going to be fundamentally some variation of the above. One common variation is to try to get rid of the if
block by doing some kind of lookup. This can be implemented using a map
object which links the name of the object to a function that instantiates it. One thing to note about this approach is that the function pointers in the map have to have the same signature, meaning theDog
and Cat
factory methods have to take the same number and type of parameters. This is a problem that can be solved using Boost::Any
(link) or other heroic methods, but that's beyond the scope of this post.
Here's a solution that implements a map
of factory method pointers:
#include <string>
#include <vector>
#include <map>
using namespace std;
class Base
{
public:
virtual ~Base() {};
};
class Dog : public Base
{
public:
static Base* make_dog() { return new Dog; }
};
class Cat : public Base
{
public:
static Base* make_cat() { return new Cat; }
};
typedef Base*(*ObjFactoryFn)();
typedef map<string, ObjFactoryFn> Factories;
int main()
{
// set up the map of object factory pointers
Factories factories;
factories["Dog"] = &Dog::make_dog;
factories["Cat"] = &Cat::make_cat;
// build list of objects we want
typedef vector<string> strings;
strings names;
names.push_back("Dog");
names.push_back("Cat");
names.push_back("Dog");
names.push_back("Cat");
// build objects using the factory map
for( strings::const_iterator it = names.begin(), it_end = names.end(); it != it_end; ++it )
{
// construct
Base* my_obj = factories[*it](); // this should use map's "find" method for robustness
// destroy
delete my_obj;
}
}