Gal*_*man 135 c++ inheritance factory instantiation
我有一个文件:Base.h
class Base;
class DerivedA : public Base;
class DerivedB : public Base;
/*etc...*/
Run Code Online (Sandbox Code Playgroud)
和另一个文件:BaseFactory.h
#include "Base.h"
class BaseFactory
{
public:
BaseFactory(const string &sClassName){msClassName = sClassName;};
Base * Create()
{
if(msClassName == "DerivedA")
{
return new DerivedA();
}
else if(msClassName == "DerivedB")
{
return new DerivedB();
}
else if(/*etc...*/)
{
/*etc...*/
}
};
private:
string msClassName;
};
/*etc.*/
Run Code Online (Sandbox Code Playgroud)
有没有办法以某种方式将此字符串转换为实际类型(类),以便BaseFactory不必知道所有可能的Derived类,并为每个类都有if()?我可以用这个字符串生成一个类吗?
我认为这可以通过Reflection在C#中完成.C++中有类似的东西吗?
Joh*_*itb 219
不,没有,除非你自己做映射.C++没有机制来创建在运行时确定其类型的对象.您可以使用地图自己进行映射:
template<typename T> Base * createInstance() { return new T; }
typedef std::map<std::string, Base*(*)()> map_type;
map_type map;
map["DerivedA"] = &createInstance<DerivedA>;
map["DerivedB"] = &createInstance<DerivedB>;
Run Code Online (Sandbox Code Playgroud)
然后你就可以做到
return map[some_string]();
Run Code Online (Sandbox Code Playgroud)
获得一个新实例.另一个想法是让类型注册自己:
// in base.hpp:
template<typename T> Base * createT() { return new T; }
struct BaseFactory {
typedef std::map<std::string, Base*(*)()> map_type;
static Base * createInstance(std::string const& s) {
map_type::iterator it = getMap()->find(s);
if(it == getMap()->end())
return 0;
return it->second();
}
protected:
static map_type * getMap() {
// never delete'ed. (exist until program termination)
// because we can't guarantee correct destruction order
if(!map) { map = new map_type; }
return map;
}
private:
static map_type * map;
};
template<typename T>
struct DerivedRegister : BaseFactory {
DerivedRegister(std::string const& s) {
getMap()->insert(std::make_pair(s, &createT<T>));
}
};
// in derivedb.hpp
class DerivedB {
...;
private:
static DerivedRegister<DerivedB> reg;
};
// in derivedb.cpp:
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
Run Code Online (Sandbox Code Playgroud)
您可以决定为注册创建宏
#define REGISTER_DEC_TYPE(NAME) \
static DerivedRegister<NAME> reg
#define REGISTER_DEF_TYPE(NAME) \
DerivedRegister<NAME> NAME::reg(#NAME)
Run Code Online (Sandbox Code Playgroud)
我相信这两个人的名字更好.在这里使用可能有意义的另一件事是shared_ptr
.
如果您有一组没有公共基类的不相关类型,则可以为函数指针指定返回类型boost::variant<A, B, C, D, ...>
.就像你有一个类Foo,Bar和Baz一样,它看起来像这样:
typedef boost::variant<Foo, Bar, Baz> variant_type;
template<typename T> variant_type createInstance() {
return variant_type(T());
}
typedef std::map<std::string, variant_type (*)()> map_type;
Run Code Online (Sandbox Code Playgroud)
A boost::variant
就像一个工会.它通过查看用于初始化或分配对象的对象来了解存储在其中的类型.在这里查看其文档.最后,使用原始函数指针也有点旧.现代C++代码应该与特定的函数/类型分离.您可能希望寻找Boost.Function
更好的方法.它看起来像这样(地图):
typedef std::map<std::string, boost::function<variant_type()> > map_type;
Run Code Online (Sandbox Code Playgroud)
std::function
将在下一版本的C++中提供,包括std::shared_ptr
.