2

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", &REGISTRY_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.

2
  • You could use free function or static member function instead of constructor. Commented May 1, 2016 at 7:06
  • Yes it would be much simpler and cleaner to use a factory/builder function. Commented May 1, 2016 at 7:08

2 Answers 2

6

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", &REGISTRY_XML::create},
}
Sign up to request clarification or add additional context in comments.

Comments

2

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();
    }
}

1 Comment

Unfortunately I cannot use C++11, only C++03 standard. So I can't use lambdas (I don't have boost in my project and I don't want to include it)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.