3

我正在使用工厂模式。它基本上允许在编译时注册类并存储在映射中。然后可以使用 BaseFactory::createInstance() 返回一个实例

我不确定地图在编译时如何保存类名!如何在运行时有效的编译时分配内存?

在这种情况下,所有类都是从父类 Bump_BaseObject 派生的

//C++ STL used for adding Reflection
#include <string>
#include <map>


class Bump_BaseObject;

/**
 * Derived Base objects creation factory
 */
template<typename T>
Bump_BaseObject* createT(void)
{
#pragma message("createT instantiated")
    return new T();
}

struct BaseFactory {
    typedef std::map<std::string, Bump_BaseObject*(*)()> map_type;

    //return an instance of the class type 's'
    static Bump_BaseObject* createInstance(const std::string& s) {
        map_type::iterator it = getMap()->find(s);
        if(it == getMap()->end())
            return 0;

        //this is where we instatiate and allocate memory for the object(it must NOT have any arguments)
        //we could write a variant that accepts args, but there is no need.
        return it->second();
    }

    //check if 's' is present in the map of registered types
    static bool checkIfRegisteredType(const std::string& s) {
        map_type::iterator it = getMap()->find(s);
        if(it == getMap()->end())
            return false;

        return true;
    }

protected:
    static map_type* getMap() {
        // never delete'ed. (exist until program termination)
        // because we can't guarantee correct destruction order
        if(!objectMap) { objectMap = new map_type; }
        return objectMap;
    }

private:
    static map_type * objectMap;
};

#define VALUE_TO_STRING(x) #x

template<typename T>
struct DerivedRegister : BaseFactory {
    DerivedRegister(const std::string& s) {


#pragma message("Type registered")
        getMap()->insert(std::pair<std::string, Bump_BaseObject*(*)()>(s, &createT<T>));
    }
};

还有一种方法可以在注册类名时打印它们吗?

4

1 回答 1

6

我认为您的代码完全混乱,将预处理器指令与奇怪的继承模式混合在一起。我不想尝试修复它,而是想展示一个通用的自注册工厂框架(它将在注册发生时打印出来)。

请注意,所有全局初始化都发生在动态初始化阶段,即在运行时main()调用之前。

基础.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);
};

基础.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 << "'\n";
}

使用示例

示例.hpp:

#include "Base.hpp"

class DerivedExample : public Base
{
    static Registrar registrar;
public:
    static Base * create() { return new DerivedExample; }
    // ...
};

示例.cpp:

#include "Example.hpp"

Registrar DerivedExample::registrar("DerivedExample", DerivedExample::create);

主文件

#include "Example.hpp"

int main()
{
    Base * p = Base::instantiate("DerivedExample");
    Base * q = Base::instantiate("AnotherExample");
}

这里的关键是每个派生类都有一个静态Registrar成员,它在程序的动态初始化阶段被初始化(以未指定的顺序),每个构造函数执行实际插入注册表映射,以及打印出日志消息。


(如果您没有现代 C++ 编译器,则必须使用旧的 C++98 样式语法:)

virtual ~Base() { }   //  no "= default"

Base::registry_map::const_iterator it = Base::registry().find(name); // no "auto"
于 2012-05-20T20:58:25.920 回答