反射:其实就是经过类的名字(类名是string)来获取类的实例。好比讲类名写在txt文件中,而后解析文本文件,拿到类名,进而那到类的实例。ios
在caffe中,在网络配置文件中,写入了各个层的名字,如:relu。其实,这些算子,在caffe源码里面都有对应的类实现,且类名一致,固然,caffe是经过protobuf来搞定配置文件的,配置文件的解析过程当中,就会经过string的类名来拿到对应类的实例,这里,其实就是运用了反射机制。网络
【反射机制实现步骤】函数
1. 创建一个工厂类,负责存储类名与建立类实例的函数的map。this
2.该工厂类提供注册函数,方便新类将其类名与类实例的建立函数放入map中。spa
3.该工厂类提供依据类名获取类实例的接口。3d
基于此,代码实现以下:指针
#include <iostream> #include <string> #include <map> using namespace std; //定义一个函数指针,来表示建立类的函数 typedef void * (*pFunc)(); // 定义一个工厂类 class DevFactory { public: static DevFactory & getInstance() { static DevFactory cf; return cf; } void * GetClassInstanceByClassName(string class_name) { auto iter = Dev_map.find(class_name); if (iter == Dev_map.end()) { cout << "can not create this " << class_name << " instance" << endl; return nullptr; } return iter->second(); } void Register(string class_name,pFunc creater){ Dev_map[class_name] = creater; } private: DevFactory() {} map<string, pFunc> Dev_map; }; class CPU { public: CPU() {} void print() { cout << "this is CPU" << endl; } }; void * creatCPU() { return new CPU; } class GPU { public: GPU() {} void print() { cout << "this is GPU" << endl; } }; void * creatGPU() { return new GPU; } int main(int argc, int * argv[]) { DevFactory dev = DevFactory::getInstance(); dev.Register("CPU", creatCPU); dev.Register("GPU",creatGPU); CPU * cpu = (CPU *)dev.GetClassInstanceByClassName("CPU"); cpu->print(); GPU *gpu = (GPU *)dev.GetClassInstanceByClassName("GPU"); gpu->print(); system("pause"); }
结果输出以下:code
【利用全局变量,实现类的自动注册】blog
基于事实:全局变量的初始化实在main函数运行以前完成的。接口
因此,咱们能够完成类的自动注册,而不用在main函数内部进行手动注册。
所以,须要一个辅助类,在该来的构造函数里面,完成注册。
代码以下:
#include <iostream> #include <string> #include <map> using namespace std; //定义一个函数指针,来表示建立类的函数 typedef void * (*pFunc)(); // 定义一个工厂类 class DevFactory { public: static DevFactory * getInstance() { static DevFactory *cf = new DevFactory; return cf; } void * GetClassInstanceByClassName(string class_name) { auto iter = Dev_map.find(class_name); if (iter == Dev_map.end()) { cout << "can not create 55 this " << class_name << " instance" << endl; return nullptr; } return iter->second(); } void Register(string class_name,pFunc creater){ cout << "register " << class_name << endl; Dev_map[class_name] = creater; } private: DevFactory() {} map<string, pFunc> Dev_map; }; class CPU { public: CPU() {} void print() { cout << "this is CPU" << endl; } }; void * creatCPU() { return new CPU; } class GPU { public: GPU() {} void print() { cout << "this is GPU" << endl; } }; void * creatGPU() { return new GPU; } class CreaterDev { public: CreaterDev(string class_name, pFunc creater) { DevFactory *dev = DevFactory::getInstance(); dev->Register(class_name, creater); } }; CreaterDev g_dev_cpu("CPU",creatCPU); //利用全局变量的初始化,自动完成注册 CreaterDev g_dev_gpu("GPU", creatGPU); int main(int argc, int * argv[]) { DevFactory *dev = DevFactory::getInstance(); //dev.Register("CPU", creatCPU); //dev.Register("GPU",creatGPU); CPU * cpu = (CPU *)dev->GetClassInstanceByClassName("CPU"); //直接依据类名获取类的实例 cpu->print(); GPU *gpu = (GPU *)dev->GetClassInstanceByClassName("GPU"); gpu->print(); system("pause"); }
结果以下:
能够看到,利用全局变量的初始化,能够方便实现新增类的自动注册。
可是也能够看出一个问题,那就是每新增一个类,都须要新增一个create函数与一个全局变量,这些代码是彻底同样的,所以,咱们能够编写一个宏,来同时实现create函数的定义与全局变量的定义。
#define REGISTER(className) \ className* objectCreator##className(){ \ return new className; \ } \ CreaterDev g_creatorRegister##className( \ #className,(pFunc)objectCreator##className)
利用这个宏,来实现类的自动注册。
所有代码以下:
#include <iostream> #include <string> #include <map> using namespace std; //定义一个函数指针,来表示建立类的函数 typedef void * (*pFunc)(); // 定义一个工厂类 class DevFactory { public: static DevFactory * getInstance() { static DevFactory *cf = new DevFactory; return cf; } void * GetClassInstanceByClassName(string class_name) { auto iter = Dev_map.find(class_name); if (iter == Dev_map.end()) { cout << "can not create 55 this " << class_name << " instance" << endl; return nullptr; } return iter->second(); } void Register(string class_name,pFunc creater){ cout << "register " << class_name << endl; Dev_map[class_name] = creater; } private: DevFactory() {} map<string, pFunc> Dev_map; }; class CreaterDev { public: CreaterDev(string class_name, pFunc creater) { DevFactory *dev = DevFactory::getInstance(); dev->Register(class_name, creater); } }; #define REGISTER(className) \ className* objectCreator##className(){ \ return new className; \ } \ CreaterDev g_creatorRegister##className( \ #className,(pFunc)objectCreator##className) class CPU { public: CPU() {} void print() { cout << "this is CPU" << endl; } }; REGISTER(CPU); class GPU { public: GPU() {} void print() { cout << "this is GPU" << endl; } }; REGISTER(GPU); int main(int argc, int * argv[]) { DevFactory *dev = DevFactory::getInstance(); //dev.Register("CPU", creatCPU); //dev.Register("GPU",creatGPU); CPU * cpu = (CPU *)dev->GetClassInstanceByClassName("CPU"); //直接依据类名获取类的实例 cpu->print(); GPU *gpu = (GPU *)dev->GetClassInstanceByClassName("GPU"); gpu->print(); system("pause"); }
结果输出以下:
能够看出,利用全局变量的初始化,能够实现类在mian以前完成好注册。固然,也有其余的方式来实现这种机制,只是这种实现方法简单,优雅。