一、对象的创建
在传统的编程手段里,创建一个对象,基本就是直接创建。几乎所有的语言都使用这种方式 。在C++的有两种方式,一种是直接创建个对象;另外一个是通过new创建一个对象并获取其指针。他们的本质都是可以得到一个对象。
而在实际的应用需求中,可能需要一种情况:就是需要通过类的名字来动态创建一个对象并投入使用。这种方式其实如果要求不是很复杂,也可以通过类似if…else之类的判断来生成。但是这样的解决方式有它的局限性,如果类比较多,比如十几个甚至几十个。另外,如果这些类的创建参数不同,也都比较难以处理。所以,这里就出现了一个问题,如何能够兼容的写出一个简单的框架来动态创建对象。
这其实也是反射里提出的一种要求,实现了它,也就是实现了通过反射创建对象的过程。
二、分析
通过上面的基本说明,可以做进一步的分析。首先,创建的这些类如果有一些共性,那么可以使用一个基类来控制这些类为其子类,那么,创建的返回结果就形成了创建一种类的这种普遍的情况;其次,如果这些类参数不同,可以把其拆解成不带参数或者统一的某个固定参数的,然后在每个类中增加init的函数,二次传参。这两种情况几乎都可以适应常见的很多种实际应用场景了。但是,可不可以直接使用不同的创建形式不做任何变换来实现呢?当然可以。
也是有两种情况:
1、将构造函数注册到一个统一的模板函数里
此处不介绍这种方法,比较麻烦,有兴趣可以自己试试。原理其实挺简单,就是声明一个函数对象(std::function)为统一的无参方式,然后其实现的函数体内调用变参模板并注册相关参数。这种方式不太友好,所以此处不就提供实际的例程了。
2、将构造函数直接保存使用
即使用一个map来保存类名和构造函数的键值对即可。这种比较好理解,也容易为大家所使用。
这里面都提出了一个问题,如何解决参数的不同的问题?以及不同的类型动态创建如何解决?这两个问题,前一个可以通过变参模板来实现,后一个可以使用模板的动态生成(全特化的不同)来实现。后者已经有了一些元编程的味道。
三、例程
基于上面的分析,看下面的代码分析即可明白:
//#include <cxxabi.h>
#include <functional>
#include <iostream>
#include <unordered_map>
char name[] = "Worker";
class Worker;
//实例工厂
template <typename T, typename... Args>
class InstanceFactory
{
public:
static InstanceFactory* Instance() {
if (nullptr == pInsFactory) {
pInsFactory = new InstanceFactory();
}
return pInsFactory;
}
~InstanceFactory() {
};
public:
// 注册
bool RegClass(const std::string& className, std::function<T* (Args &&...args)> func) {
if (nullptr == func) {
return false;
}
return insFunc_.emplace(className, func).second