模板+函数对象处理重复函数语句
问题:传入一个基类,想要获取子类特有的函数传出的数据。比如ChildA想获取Get的int型数据,ChildB想获取Get的string型数据。
class Base { public: Base() {}; virtual ~Base() {}; virtual int GetType() = 0; }; class ChildA :public Base { public: ChildA() {}; virtual ~ChildA() {}; int Get() { return 10; }; virtual int GetType() { return 1; }; }; class ChildB :public Base { public: ChildB() {}; virtual ~ChildB() {}; string Get() { return "ChildB"; }; virtual int GetType() { return 2; }; };
普通的做法是:先判断传的类型是什么,然后选择对应的函数进行处理。
struct Info { int sChildA; //存A的信息 string sChildB; //存B的信息 }; //获取ChildA的get值 void GetAInfo(Base* a, int& d) { ChildA* b = dynamic_cast<ChildA*>(a); if (!b) { return; } d = b->Get(); } //获取ChildA的get值 void GetBInfo(Base* a, string& d) { ChildB* b = dynamic_cast<ChildB*>(a); if (!b) { return; } d = b->Get(); } //根据不同的base获取信息 void DealWith(Base* base, Info& info) { int type = base->GetType(); switch (type) { case 1: GetAInfo(base, info.sChildA); break; case 2: GetBInfo(base, info.sChildB); break; default: break; } }
最终结果:
方法一:采用模板处理,传类型的时候,传入类的默认构造
struct Info { int sChildA; //存A的信息 string sChildB; //存B的信息 }; //模板函数获取Get值 template<typename T, typename M> void GetInfo(Base* a, T c, M& d) { T* b = dynamic_cast<T*>(a); if (!b) { return; } d = b->Get(); } //根据不同的base获取信息 void DealWith(Base* base, Info& info) { int type = base->GetType(); switch (type) { case 1: //采用类的默认构造传类型 GetInfo(base, ChildA(), info.sChildA); break; case 2: GetInfo(base, ChildB(), info.sChildB); break; default: break; } }
结果:
但是当函数不支持默认构造,可能需要传参才能构造出来,这样就复杂了,方法一就不适用了。
class Base { public: Base(int a) {}; virtual ~Base() {}; virtual int GetType() = 0; }; class ChildA :public Base { public: ChildA(int a):Base(a) {}; virtual ~ChildA() {}; int Get() { return 10; }; virtual int GetType() { return 1; }; }; class ChildB :public Base { public: ChildB(int a) :Base(a) {}; virtual ~ChildB() {}; string Get() { return "ChildB"; }; virtual int GetType() { return 2; }; };
方法三:不加函数名,直接模板
//模板函数获取Get值 template<typename T, typename M> void GetInfo(Base* a, M& d) { T* b = dynamic_cast<T*>(a); if (!b) { return; } d = b->Get(); } //根据不同的base获取信息 void DealWith(Base* base, Info& info) { int type = base->GetType(); switch (type) { case 1: //采用类的默认构造传类型 GetInfo<ChildA>(base, info.sChildA); break; case 2: GetInfo<ChildB>(base, info.sChildB); break; default: break; }
方法四:这时候模板+函数对象就登场了。
struct Info { int sChildA; //存A的信息 string sChildB; //存B的信息 }; //模板+函数对象 处理 template<typename T, typename M> struct GetInfo { public: void operator()(Base* a, M& d) { T* b = dynamic_cast<T*>(a); if (!b) { return; } d = b->Get(); } }; //根据不同的base获取信息 void DealWith(Base* base, Info& info) { int type = base->GetType(); switch (type) { case 1: GetInfo<ChildA,int> childa; childa(base, info.sChildA); break; case 2: GetInfo<ChildA, string> childb; childb(base, info.sChildB); break; default: break; } }