I think your code is altogether confused, mixing preprocessor directives with strange inheritance patterns. Instead of trying to fix it, I'd like to present a generic, self-registering factory framework (which will print out registrations as they happen).
Note that all global initialization happens during the dynamic initialization phase, i.e. at runtime just before main()
is called.
Base.hpp:
#include <unordered_map>
#include <string>
class Base
{
public:
typedef Base * (*base_creator_fn)();
typedef std::unordered_map<std::string, base_creator_fn> registry_map;
virtual ~Base() = default;
static registry_map & registry();
static Base * instantiate(std::string const & name);
};
struct Registrar
{
Registrar(std::string name, Base::base_creator_fn func);
};
Base.cpp:
#include "Base.hpp"
#include <iostream>
registry_map & Base::registry()
{
static registry_map impl;
return impl;
}
Base * Base::instantiate(std::string const & name)
{
auto it = Base::registry().find(name);
return it == Base::registry().end() ? nullptr : (it->second)();
}
Registrar::Registrar(std::string name, Base::base_creator_fn func)
{
Base::registry()[name] = func;
std::cout << "Registering class '" << name << "'
";
}
Usage Example
Example.hpp:
#include "Base.hpp"
class DerivedExample : public Base
{
static Registrar registrar;
public:
static Base * create() { return new DerivedExample; }
// ...
};
Example.cpp:
#include "Example.hpp"
Registrar DerivedExample::registrar("DerivedExample", DerivedExample::create);
Main.cpp
#include "Example.hpp"
int main()
{
Base * p = Base::instantiate("DerivedExample");
Base * q = Base::instantiate("AnotherExample");
}
The crux here is that each derived class has a static Registrar
member, which gets initialized (in unspecified order) during the dynamic initialization phase of your program, and each constructor of which performs the actual insertion into the registry map, as well as printing out of the log message.
(If you don't have a modern C++ compiler, you would have to use the old C++98-style syntax:)
virtual ~Base() { } // no "= default"
Base::registry_map::const_iterator it = Base::registry().find(name); // no "auto"
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…