和网上大多数实现一样,这里也是采用工厂方法来实现对象的动态创建。大致原理为,创建一个单例工厂类,其中维护一个map(类名->对象创建函数)。创建对象时,传入类名,然后根据此类名查询出创建函数,最后创建对象。
采用这种方式,有一个关键问题,便是在工厂中注册类名。我们的办法是针对于每一个类(Class),定义一个注册类(ClassReg),在注册类(ClassReg)的构造函数中注册此类(Class),然后再定义一个注册类的全局对象,在该全局对象初始化时,便会执行注册代码完成注册。
看到到这里懒人不乐意了,难道我们每写一个类,还要写一个相应的注册类?于是有人提出了使用宏来替换相应的代码,这样便大大减少了重复代码量。
采用宏当然可以,但是只能满足部分懒人。还有一部分人更懒,他们连使用这个宏完成注册都不想干,是呀,每写完一个类,还要在类后面使用宏来注册,这样确实还是比较麻烦。而且这样代码不够美观,也不便于维护,同时采用宏来转换类名,遇到命名空间,嵌套类,会非常麻烦,我们必须在注册的时候,把名字写全,比如REG_CLASS(MyNameSpace::MyClass::MyStruct)。
那么有没有更好的方法呢?当然有,我们可以用类模板来实现这种功能。设想这种方式,若我们要定义一个类MyClass,并且想让此类支持动态创建,那么我们只需这样定义即可class MyClass : public DynamicCreate<MyClass>{};。这样是不是清晰多了?下面请看代码:
DynamicFactory.h文件
-
#ifndef __DYNAMIC_FACTORY_H__
-
#define __DYNAMIC_FACTORY_H__
-
-
#ifdef __GNUC__
-
#include <cxxabi.h>
-
#endif
-
-
#include <assert.h>
-
#include <string.h>
-
#include <stdlib.h>
-
#include <map>
-
#include <string>
-
#include <typeinfo>
-
-
// 动态对象基类
-
class DynamicObject
-
{
-
public:
-
DynamicObject() {}
-
virtual ~DynamicObject() {}
-
};
-
-
// 动态对象创建工厂
-
class DynamicFactory
-
{
-
public:
-
-
typedef DynamicObject* (*CreateFunction)();
-
-
static DynamicFactory & Instance()
-
{
-
static DynamicFactory fac;
-
return fac;
-
}
-
-
// 解析类型名称(转换为 A::B::C 的形式)
-
static
std::
string ReadTypeName(const char * name)
-
{
-
// 这里省略,具体代码在最后给出
-
...
-
}
-
-
bool Regist(const char * name, CreateFunction func)
-
{
-
if (!func)
-
{
-
return
false;
-
}
-
std::
string type_name = ReadTypeName(name);
-
return _create_function_map.insert(
std::make_pair(type_name, func)).second;
-
}
-
-
DynamicObject * Create(const std::string & type_name)
-
{
-
if (type_name.empty())
-
{
-
return
NULL;
-
}
-
-
std::
map<
std::
string, CreateFunction>::iterator it = _create_function_map.find(type_name);
-
if (it == _create_function_map.end())
-
{
-
return
NULL;
-
}
-
-
return it->second();
-
}
-
-
template<
typename T>
-
T * Create(const std::string & type_name)
-
{
-
DynamicObject * obj = Create(type_name);
-
if (!obj)
-
{
-
return
NULL;
-
}
-
T * real_obj =
dynamic_cast<T*>(obj);
-
if (!real_obj)
-
{
-
delete obj;
-
return
NULL;
-
}
-
return real_obj;
-
}
-
-
public:
-
-
std::
map<
std::
string, CreateFunction> _create_function_map;
-
};
-
-
// 动态对象创建器
-
template<
typename T>
-
class DynamicCreate :
public DynamicObject
-
{
-
public:
-
static DynamicObject * CreateObject()
-
{
-
return
new T();
-
}
-
-
struct Registor
-
{
-
Registor()
-
{
-
if (!DynamicFactory::Instance().Regist(
typeid(T).name(), CreateObject))
-
{
-
assert(
false);
-
}
-
}
-
-
inline void do_nothing()const { }
-
};
-
-
static Registor s_registor;
-
-
public:
-
DynamicCreate()
-
{
-
s_registor.do_nothing();
-
}
-
-
virtual ~DynamicCreate()
-
{
-
s_registor.do_nothing();
-
}
-
};
-
-
template <
typename T>
-
typename DynamicCreate<T>::Registor DynamicCreate<T>::s_registor;
-
-
#endif
代码不多,就不做解释了。
测试代码mian.cpp
-
#include <stdio.h>
-
#include "DynamicFactory.h"
-
-
class Test1 :
public DynamicCreate<Test1>
-
{
-
public:
-
// 注意:使用gcc,一定要显示申明构造函数,否则不会执行注册代码
-
Test1() {}
-
};
-
-
namespace OK {
-
struct Test2 :
public DynamicCreate<Test2>
-
{
-
Test2() {}
-
-
class Test3 :
public DynamicCreate<Test3>
-
{
-
public:
-
Test3() {}
-
};
-
};
-
-
struct Test4 :
public DynamicCreate<Test4>
-
{
-
Test4() {}
-
};
-
}
-
-
using
namespace OK;
-
-
//测试代码
-
int main()
-
{
-
Test1 * p1 = DynamicFactory::Instance().Create<Test1>(
"Test1");
-
printf(
"Create Test1 %s\n", (p1 ?
"success" :
"failure"));
-
-
OK::Test2 * p2 = DynamicFactory::Instance().Create<OK::Test2>(
"OK::Test2");
-
printf(
"Create OK::Test2 %s\n", (p2 ?
"success" :
"failure"));
-
-
OK::Test2::Test3 * p3 = DynamicFactory::Instance().Create<OK::Test2::Test3>(
"OK::Test2::Test3");
-
printf(
"Create OK::Test2::Test3 %s\n", (p3 ?
"success" :
"failure"));
-
-
OK::Test4 * p4 = DynamicFactory::Instance().Create<OK::Test4>(
"OK::Test4");
-
printf(
"Create OK::Test4 %s\n", (p4 ?
"success" :
"failure"));
-
-
return
0;
-
}
输出:
[programmer@localhost test]$ ./test
Create Test1 success
Create OK::Test2 success
Create OK::Test2::Test3 success
Create OK::Test4 success
下面给出上面省略的 ReadTypeName函数代码
-
// 解析类型名称(转换为 A::B::C 的形式)
-
// GCC 的type_info::name()输出的名称很猥琐,这里只做简单的解析,只支持自定义的结构体(非模板),类(非模板)、枚举、联合
-
static
std::
string ReadTypeName(const char * name)
-
{
-
#ifndef __GNUC__
-
const
char * p =
strstr(name,
" ");
-
if (p)
-
{
-
size_t prev_len = (
size_t)(p - name);
-
if (
memcmp(name,
"class", prev_len) ==
0 ||
-
memcmp(name,
"struct", prev_len) ==
0 ||
-
memcmp(name,
"enum", prev_len) ==
0 ||
-
memcmp(name,
"union", prev_len) ==
0)
-
{
-
p +=
1;
-
return
std::
string(p);
-
}
-
}
-
-
return
std::
string(name);
-
#else
-
char * real_name = abi::__cxa_demangle(name,
nullptr,
nullptr,
nullptr);
-
std::
string real_name_string(real_name);
-
free(real_name);
-
return real_name_string;
-
#endif
-
}