class A
{
};
A * classASpawner()
{
returnnew A;
}
class B : public A
{
};
A* classBSpawner()
{
returnnew B;
}
std::unordered_map <std::string, A* (*spawner)()> factory;
void registerSpawner(std::string className, A* (*spawner)())
{
factory[className] = spawner;
}
/// Somewhere else while loading from a text file
A* loadFile(std::string filePath)
{
std::ifstream ifile(filePath.c_str());
while(good)
{
std::string className;
ifile >> className;
myVector.push_back(factory[className]());
// now the myVector is being loaded with both A's and B's without
// really caring which is which. Polymorphism taking care of that.
// Of course this requires parsing and reading in the data for each object too, but
// this was the basic idea.
}
}
- Sorry, that's all typed in-place, not meant to run as-is.
So is there a way to register a class constructor and cut out the man in the middle spawner function?
Is there a better way to create an object from a file?
Here's a working example, similar to what is found in the stack overflow link, but it proves to me how easy this will be to plug into my much larger code base;
// Create a factory that takes a string, outputs a new item without a spawner function as a middleman
#include <unordered_map>
#include <functional>
#include <iostream>
class base
{
public:
base();
int val;
};
base::base()
{
std::cout << "Base type created.\n";
val = 1;
}
class child : public base
{
public:
child();
};
child::child()
{
std::cout << "Child type created.\n";
}
std::unordered_map <std::string, std::function<base*()> > types;
template <typename T> void registerType(std::string type)
{
types[type] = []()
{
returnnew T;
};
}
base * getObj(std::string type)
{
return types[type]();
}
int main()
{
registerType<base>("base");
registerType<child>("child");
base * t1 = getObj("base");
base * t2 = getObj("child");
delete t1;
delete t2;
}
Your last post doesn't need the stuff in functional. A plain function pointer will still work just fine. You just have to specify the anonymous function's return type.
The key use that I get out of the "factory method" is that I can save the details of an object in an XML file (human readable/editable text data file). Now my objects can be modified by data files rather than everything being hard-coded. If I want to add a new goblin in the top left corner of a board I now just add a single line in the xml data file and the changes are made without even having to recompile the program.
The reason that the template is so important is that this is for a system of dynamically loaded object files, so I can't know every class type available until the plugin file registers it. Instead of each plugin needing to create a similar function, the plugin just needs to call registerType in order to use the functionality on classes that it wants to be able to load.
As long as "goblin" has been registered by the plugin, I can call getObj("goblin") and load the rest of the data into the new goblin object as I parse the attributes.