反射:其實就是經過類的名字(類名是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以前完成好註冊。固然,也有其餘的方式來實現這種機制,只是這種實現方法簡單,優雅。