在编译时分配内存的工厂模式,以及如何打印编译时信息
Factory pattern allocating memory at compile time, and how to print compile time info
我使用的是工厂模式。它基本上允许类在编译时注册并存储在映射中。然后可以使用 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>));
}
};
还有没有办法在注册时打印类名?
我认为您的代码完全混乱,将预处理器指令与奇怪的继承模式混合在一起。与其尝试修复它,我想提供一个通用的、自注册的工厂框架(它将在注册发生时打印出来(。
请注意,所有全局初始化都发生在动态初始化阶段,即在调用main()
之前的运行时。
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);
};
基.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);
主.cpp
#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"
相关文章:
- 如何循环打印顶点结构
- 为什么在popback()操作之后,它仍然打印完整的矢量
- 在 C++11 中打印编译时整数序列
- Android Studio,CMake.如何在编译时打印调试消息
- 如何在编译时打印常量值
- 如何在编译时漂亮地打印模板参数的名称
- 如何在C++中打印编译时计算的结果
- 即使编译正常,cuPrintf也不会打印任何内容
- 在编译时分配内存的工厂模式,以及如何打印编译时信息
- 将 Qt 中的 Git 哈希打印为编译时创建的宏
- 使用 #pragma message() 打印编译期间 #define 的完整评估结果
- 用 Mingw 编译的 C++ 文件不打印 Hello World
- 能够编译和运行.然而,当运行代码时,它不能打印我想打印的任何值
- 继续使用g++和Makefiles从编译后的代码中打印编译器警告
- 在编译时打印sizeof(T)
- 编译SAX打印示例(示例)
- 打印Visual Studio用于编译文件的整个命令
- 我的包编译后,get函数可以工作,除了它打印随机数的doubles
- 服务器设置在编译时保持打印"connected"即使没有连接客户端
- 编译时从发布二进制文件中删除调试打印