一点东西
题目也可以是函数表(用于存储指向可调用对象的”指针”).
1 2 3 4 5 6 7 8 9 10 11 | //普通函数 int add(int i,int j){ return i+j; } //lambda,其产生一个未命名的函数对象类. auto mod = [](const int &i,const int &j){ return i+j; } //函数对象类. struct divide{ int operator()(int denominator,int divisor) { return denominator / divisor; } }; |
上面这些可调用对象,虽然类型不同,但是共享同一种调用形式:
1 | int(int,int) |
可以定义一个函数表,用于存储指向这些可调用对象的”指针”.当程序需要执行某个特定的操作时,
从表中查找该调用的函数.
在C++中,函数表很容易通过map来实现.
简单意思就是将与int(int,int)一样的类型,放入一个map中,将其的操作作为map的主键.
形如:
1 2 3 4 | map["+"]=add;//add是一个函数指针. map["-"]=minus;//同add的含义一样. map["*"]=.. 以此类推.. |
代码实现
下面的代码可以运行,推荐一个在线运行的网址:CPP.SH
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | // Example program #include <iostream> #include <string> #include <map> #include<functional> using namespace std; /* //普通函数 int add(int i,int j){ return i+j; } //lambda,其产生一个未命名的函数对象类. auto mod = [](const int &i,const int &j){ return i+j; } //函数对象类. struct divide{ int operator()(int denominator,int divisor) { return denominator / divisor; } }; 上面这些可调用对象,虽然类型不同,但是共享同一种调用形式: int(int,int) 可以定义一个函数表,用于存储指向这些可调用对象的"指针".当程序需要执行某个特定的操作时, 从表中查找该调用的函数. 在C++中,函数表很容易通过map来实现. */ int add(int i,int j){ return i+j; } struct divide{ int operator()(int denominator,int divisor) { return denominator / divisor; } }; int main() { auto mod = [](const int &i,const int &j){ return i+j; }; map<string,int(*)(int,int)> binops; binops.insert({"+",add}); //但是我们不能将mod或者divide存入binops.因为mod不是一个函数指针. //问题在于mod是个lambda表达式,而每个lambda有它自己的类类型,该类型与存储在binops中的值得类型不匹配. //解决办法如下: //使用一个名为function的新的标准库类型解决上述问题. /*function<int(int,int)> f1 = add;//函数指针 function<int(int,int)> f2 = divide();//函数对象类的对象. function<int(int,int)> f3 = [](int i,int j){ return i * j ; }; //lambda cout << f1(4,2) << endl; cout << f2(4,2) << endl; cout << f3(4,2) << endl;*/ //使用function类型我们可以重新定义map. map<string,function<int(int,int)>> binops2={ {"+",add}, //函数指针. {"-",std::minus<int>()}, //标准库函数对象 {"/",divide()}, //用户定义的函数对象. {"*",[](int i,int j){ return i * j ;}}, //未命名的lambda {"%",mod} //命名了的lambda对象 }; cout << "10+5=" << binops2["+"](10,5) << endl;//调用add(10,5) cout << "10-5=" << binops2["-"](10,5) << endl;//调用minus<int> cout << "10/5=" << binops2["/"](10,5) << endl;//调用divide cout << "10*5=" << binops2["*"](10,5) << endl;//调用lambda cout << "10%5=" << binops2["%"](10,5) << endl;//调用lambda /* 我们不能(直接)将重载函数的名字存入function类型的对象中: int add(int i,int j){return i+j;} Sales_data add(const Sales_data&,const Sales_data&); map<string,function<int(int,int)>> binops3; binops3.insert({"+",add}); //错误:哪个add? 解决上述二义性的问题是存储函数指针而非函数的名字: int (*fp)(int,int) =add; //指针所指的add是接受两个int的版本. binops3.insert({"+",fp}); //正确:fp指向一个正确的add版本 同样,也可以用lambda来消除二义性: //正确:使用lambda来指定我们希望使用的add版本 binops3.insert({"+",[](int a,int b){return add(a,b);}}); */ return 0; } |