switch-case 采用map+函数指针替代

个人觉得不能一味排斥和推崇采用其他方法替代switch-case。

但如果对于一些情况采用map+函数指针去替代switch会极大的优化代码,整洁和使代码不会那么膨胀。

对于多个函数的参数相同的情况下,采用map+函数指针。

对于函数在类内处理方法有两种:

1.因为map的时候要取函数地址指针,将函数单独开辟地址空间采用static(这个方法不好

2.采用提前声明,用函数指针。(推荐这种

class A;
using Func = int (A::*)(int);

3.采用map+function+bind方法,用函数指针。(推荐这种

比如:分别case 为1,2,3 分别执行不同的函数,如果有很多函数就会导致代码臃肿。

class A
{
public:
    int test1(int a);
    int test2(int a);
    int test3(int a);
    int GetTest(int a);
};
int A::test1(int a)
{
    return 1;
}
int A::test2(int a)
{
    return 2;
}
int A::test3(int a)
{
    return 3;
}
int A::GetTest(int a)
{
    int data = 0;
    switch (a)
    {
    case 1:
        data = test1(10);
        break;
    case 2:
        data = test1(10);
        break;
    case 3:
        data = test1(10);
        break;
    default:
        break;
    }
    return data;
}
int main()
{
    A a;
    int data = a.GetTest(1);
    return 0;
}

通过map+函数指针可以处理这种情况。

需要注意:先声明一下类,然后用类型别名 注意用A::*。(这种处理是函数在类内的时候要这么处理),主要是要取函数的地址指针。不采用这个方法也行,可以把函数加static处理,单独给函数开辟一个地址,不建议这么处理。

函数被取出了的时候要用

(this->*data->second)(a);

不然会报错:明显调用的表达式前的括号必须具有(指针)函数类型

class A;
using Func = int (A::*)(int);

using namespace std;
class A;
using Func = int (A::*)(int);
class A
{
public:
    void initMap();
    int test1(int a);
    int test2(int a);
    int test3(int a);
    optional<int> GetTest(int a);
private:
    map<int, Func> infoMap;
};
int A::test1(int a)
{
    return 1;
}
int A::test2(int a)
{
    return 2;
}
int A::test3(int a)
{
    return 3;
}
void A::initMap()
{
    map<int, Func> dataMap = {
        {1,&A::test1},
        {2,&A::test2},
        {3,&A::test3},
    };
    infoMap.swap(dataMap);
}

//C++17 optinal<T>等于bool +其类型T
optional<int> A::GetTest(int a)
{
    optional<int> info;
    if (auto data = infoMap.find(a); infoMap.end()!= data)
    {
        info = (this->*data->second)(a);
    }
    return info;
}
int main()
{
    A a;
    a.initMap();
    optional<int> data = a.GetTest(1);
    if (!data.has_value())
    {
        cout << "has no tag" << endl;
    }
    else
        cout << "data is :" << *data << endl;
    return 0;
}

3.map+function+bind

using namespace std;

using Func = function<int(int)>;
class A
{
public:
    void initMap();
    int test1(int a);
    int test2(int a);
    int test3(int a);
    optional<int> GetTest(int a);
private:
    map<int, Func> infoMap;
};
int A::test1(int a)
{
    return 1;
}
int A::test2(int a)
{
    return 2;
}
int A::test3(int a)
{
    return 3;
}
void A::initMap()
{
    map<int, Func> dataMap = {
        {1,std::bind(&A::test1,this, std::placeholders::_1)},
        {2,std::bind(&A::test2,this, std::placeholders::_1)},
        {3,std::bind(&A::test3,this, std::placeholders::_1)},
    };
    infoMap.swap(dataMap);
}

//C++17 optinal<T>等于bool +其类型T
optional<int> A::GetTest(int a)
{
    optional<int> info;
    if (auto data = infoMap.find(a); infoMap.end() != data)
    {
        info = data->second(a);
    }
    return info;
}
int main()
{
    A a;
    a.initMap();
    optional<int> data = a.GetTest(1);
    if (!data.has_value())
    {
        cout << "has no tag" << endl;
    }
    else
        cout << "data is :" << *data << endl;
    return 0;
}

4.采用map+可变模板参数+function+bind方法,用函数指针

针对于多参数的test函数可以采用可变参数模版进行处理,但仍有限制的地方

限制的地方:

1.map中的func必须指定参数类型。

2.进行变量输入需要额外指定。

template<typename... Args>
using func = function<int(Args...)>;
class A
{
public:
	void initMap();
	int test1(int a, string b);
	int test2(int a);
	template<typename... Args>
	int findMap(int num, Args...);
private:
	map<int, func<int,string>> infoMap;
};

int A::test1(int a,string b)
{
	return 1;
}
int A::test2(int a)
{
	return 2;
}

void A::initMap()
{
	map<int, func<int,string>> dataMap = {
		{1,std::bind(&A::test1,this, std::placeholders::_1,std::placeholders::_2)},
		{2,std::bind(&A::test2,this, std::placeholders::_1)},
	};
	infoMap.swap(dataMap);
}

template<typename... Args>
int A::findMap(int num,Args... args)
{
	auto iter = infoMap.find(num);
	if (iter!= infoMap.end())
	{
		return iter->second(args...);
	}
	return 0;
}

int main(void)
{
	A a;
	a.initMap();
	cout << a.findMap(1, 1, "") << endl;
	cout << a.findMap(2,5,"string") << endl;
	return 0;
}

 

5.采用map+function+any+bind方法,处理多参数函数(推荐这种)

using func = function<int(any)>;
class A
{
public:
	A();
	int test1(any data);
	int test2(any data);
	int findMap(int num,any data);
private:
	map<int, func> infoMap;
};

int A::test1(any data)
{
	//对any进行处理
	return 1;
}
int A::test2(any data)
{
	//对any进行处理
	return 2;
}

A::A()
{
	map<int, func> dataMap = {
		{1,std::bind(&A::test1,this, std::placeholders::_1)},
		{2,std::bind(&A::test2,this, std::placeholders::_1)},
	};
	infoMap.swap(dataMap);
}

int A::findMap(int num, any data)
{
	auto iter = infoMap.find(num);
	if (iter!= infoMap.end())
	{
		return iter->second(data);
	}
	return 0;
}

struct TypeA
{
public:
	TypeA(const int& i, const string& s) :x(i), str(s) {};
	int x;
	string str;
};

struct TypeB
{
public:
	TypeB(const int& i, const double& s) :x(i), y(s) {};
	int x;
	double y;
};

int main(void)
{
	A a;
	TypeA ta(10,"test");
	TypeB tb(20, 30);
	any dataA = ta, dataB = tb;
	cout << a.findMap(1, dataA) << endl;
	cout << a.findMap(2, dataB) << endl;
	return 0;
}

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值