模板+函数对象处理重复函数语句
问题:传入一个基类,想要获取子类特有的函数传出的数据。比如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;
}
}
