个人觉得不能一味排斥和推崇采用其他方法替代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;
}