C++ 中的 object 工厂字典
An object factory dictionary in C++
我需要实现一个静态映射,使我能够在给定字符串的情况下检索新的 objects:
Header:
static const map<string, function<void(MyObject)>> Dictionary;
来源:
const map<string, function<void(MyObject)>> * const ObjectDictionary = boost::assign::map_list_of
("Car", new MyCarObject())
("Ship", new MyShipObject());
但是我在编译时遇到了问题:
'<function-style-cast>': cannot convert from 'initializer list' to 'std::pair<const char *,MyCarObject *>'
我也不确定这个工厂的用途。
如何在 C++ 中实现此行为?
注意:我正在尝试做的是将我过去所做的一些代码从 C# 移植到 C++:
public static class MyFactory
{
public static readonly Dictionary<string, Func<MyObject>> ObjectDictionary = new Dictionary<string, Func<MyObject>>()
{
["Car"] = () => new MyCarObject(),
["Ship"] = () => new MyShipObject(),
};
}
所以我可以读取文本文件并创建 objects 给定的字符串:
var getObject = default(Func<MyObject>);
CurrentObjectDictionary.TryGetvalue(objectName, out getObject);
if(getObject != null)
{
MyObject = getObject();
//MyObject.Data = ...
//store
}
您可以直接使用创建者函数初始化地图,无需 boost 往返。
const std::map<std::string, std::function<unique_ptr<Object>()>> dict{
{"car", [](){ return std::make_unique<MyCarObject>();}},
{"ship", [](){ return std::make_unique<MyShipObject>();}}
};
用法:
auto vehicle = dict.at(vehicle_type)();
注意:如果您只处理 nullary 构造函数,您甚至可以只将 &std::make_unique<T>
插入到映射中:
const map<...> dict{
{"car", &std::make_unique<Car>},
{"ship", &std::make_unique<Ship>}
};
class Transport
{
public:
virtual ~Transport();
virtual void foo() = 0;
};
class Car : public Transport
{
public:
virtual ~Car();
virtual void foo(){ };
};
class Boat : public Transport
{
public:
virtual ~Boat();
virtual void foo(){ };
};
typedef boost::function<Transport*()> factoryfunc;
template<typename T>
static std::unique_ptr<T> CreateObject()
{
return std::unique_ptr<T>{new T()};
}
class foo
{
public:
foo()
{
map_.insert(std::make_pair("car", CreateObject<Car>));
map_.insert(std::make_pair("boat", CreateObject<Boat>));
}
std::map<std::string, factoryfunc> map_;
};
您可以这样使用:
foo obj;
Transport* carobj = obj.map_["car"]();
这只是一个示例,旨在为您提供一个思路。那里有动态分配,没有您可能想要改进的删除等。需要注意的关键是插入时添加到地图中的内容。它不是实际对象,而是所提到的签名的函数。然后我调用函数来获取 return 中的对象,例如:Transport* carobj = obj.map_["car"]();
我需要实现一个静态映射,使我能够在给定字符串的情况下检索新的 objects:
Header:
static const map<string, function<void(MyObject)>> Dictionary;
来源:
const map<string, function<void(MyObject)>> * const ObjectDictionary = boost::assign::map_list_of
("Car", new MyCarObject())
("Ship", new MyShipObject());
但是我在编译时遇到了问题:
'<function-style-cast>': cannot convert from 'initializer list' to 'std::pair<const char *,MyCarObject *>'
我也不确定这个工厂的用途。
如何在 C++ 中实现此行为?
注意:我正在尝试做的是将我过去所做的一些代码从 C# 移植到 C++:
public static class MyFactory
{
public static readonly Dictionary<string, Func<MyObject>> ObjectDictionary = new Dictionary<string, Func<MyObject>>()
{
["Car"] = () => new MyCarObject(),
["Ship"] = () => new MyShipObject(),
};
}
所以我可以读取文本文件并创建 objects 给定的字符串:
var getObject = default(Func<MyObject>);
CurrentObjectDictionary.TryGetvalue(objectName, out getObject);
if(getObject != null)
{
MyObject = getObject();
//MyObject.Data = ...
//store
}
您可以直接使用创建者函数初始化地图,无需 boost 往返。
const std::map<std::string, std::function<unique_ptr<Object>()>> dict{
{"car", [](){ return std::make_unique<MyCarObject>();}},
{"ship", [](){ return std::make_unique<MyShipObject>();}}
};
用法:
auto vehicle = dict.at(vehicle_type)();
注意:如果您只处理 nullary 构造函数,您甚至可以只将 &std::make_unique<T>
插入到映射中:
const map<...> dict{
{"car", &std::make_unique<Car>},
{"ship", &std::make_unique<Ship>}
};
class Transport
{
public:
virtual ~Transport();
virtual void foo() = 0;
};
class Car : public Transport
{
public:
virtual ~Car();
virtual void foo(){ };
};
class Boat : public Transport
{
public:
virtual ~Boat();
virtual void foo(){ };
};
typedef boost::function<Transport*()> factoryfunc;
template<typename T>
static std::unique_ptr<T> CreateObject()
{
return std::unique_ptr<T>{new T()};
}
class foo
{
public:
foo()
{
map_.insert(std::make_pair("car", CreateObject<Car>));
map_.insert(std::make_pair("boat", CreateObject<Boat>));
}
std::map<std::string, factoryfunc> map_;
};
您可以这样使用:
foo obj;
Transport* carobj = obj.map_["car"]();
这只是一个示例,旨在为您提供一个思路。那里有动态分配,没有您可能想要改进的删除等。需要注意的关键是插入时添加到地图中的内容。它不是实际对象,而是所提到的签名的函数。然后我调用函数来获取 return 中的对象,例如:Transport* carobj = obj.map_["car"]();