模板+函数对象处理重复函数语句

问题:传入一个基类,想要获取子类特有的函数传出的数据。比如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;
	}
}
经验分享 程序员 微信小程序 职场和发展