Reputation: 635
I have several classes named Child1, Child2 ... etc, inherited from object Parent. I need to create an object by its name, for example if I have string "Child1", I need to create object Child1 and so on.
I thought about something like:
struct registry_entry {
const char* name;
IREGISTRY* (*initializer)();
};
struct registry_entry registry_list[] =
{
{"xml", ®ISTRY_XML::REGISTRY_XML},
}
But I can't get address of object constructor.I believe that this problem must be already solved, and the solution is pretty simple, but I can't find it.
Upvotes: 2
Views: 101
Reputation: 27528
Your code looks very C-like and not very C++-like, but if you can actually use the full power of C++11, I would go with a combination of std::function
, lambdas, std::unique_ptr
and std::map
.
Lambdas can wrap constructors without you having to write separate wrapper functions, std::function
allows you to store the lambdas in a map, std::unique_ptr
eliminates many memory-management bugs, and std::map
performs the actual mapping from strings to initialiser functions.
Here is a complete example:
#include <functional>
#include <string>
#include <memory>
#include <map>
#include <iostream>
struct IREGISTRY {
virtual ~IREGISTRY() {}
virtual void print() = 0;
};
struct REGISTRY_XML : IREGISTRY { void print() override { std::cout << "XML\n"; } };
struct REGISTRY_INI : IREGISTRY { void print() override { std::cout << "INI\n"; } };
struct REGISTRY_JSON : IREGISTRY { void print() override { std::cout << "JSON\n"; } };
int main()
{
std::map<std::string, std::function<std::unique_ptr<IREGISTRY>()>> const registry_list = {
{ "xml", []() { return std::make_unique<REGISTRY_XML>(); } },
{ "ini", []() { return std::make_unique<REGISTRY_INI>(); } },
{ "json", []() { return std::make_unique<REGISTRY_JSON>(); } },
};
auto const initializer_iter = registry_list.find("xml");
if (initializer_iter != registry_list.end())
{
auto const initializer = initializer_iter->second;
auto const registry_ptr = initializer();
registry_ptr->print();
}
}
Upvotes: 2
Reputation: 1
Constructors and destructors are special functions and cannot be accessed through function pointers.
You need to create a static member function like
struct REGISTRY_XML {
static IREGISTRY* create();
};
thus you can refer to it as
struct registry_entry registry_list[] =
{
{"xml", ®ISTRY_XML::create},
}
Upvotes: 6