我有函数Mult, Add, Div, Sub, Mod
那些取两个整数并返回其参数的结果。还有一个函数Calc
,它将一个字符作为Operator
并返回一个指向函数的指针,该函数返回一个整数并获取两个整数参数,如Mult
。
Mult
的第二个参数这样的函数是default
所以当我调用Calc
时,Calc
返回Mult
或Add
的地址......取决于Calc
的参数值,因此我只能传递一个参数。但它不适用于指向函数的指针:
int Add(int x, int y = 2) { // y is default
return x + y;
}
int Mult(int x, int y = 2) { // y is default
return x * y;
}
int Div(int x, int y = 2) { // y is default
return y ? x / y : -1;
}
int Sub(int x, int y = 2) { // y is default
return x - y;
}
int Mod(int x, int y = 2) { // y is default
return y ? x % y : -1;
}
using pFn = int(*)(int, int);
pFn Calc(char c) {
switch (c) {
case '+':
return Add;
case '*':
return Mult;
case '/':
return Div;
case '-':
return Sub;
case '%':
return Mod;
}
return Mult;
}
int main(int argc, char* argv[]){
pFn func = Calc('%');
cout << func(7, 4) << endl; // ok
//cout << func(7) << endl; // error: Too few arguments
cout << Mult(4) << endl; // ok. the second argument is default
func = Calc('/'); // ok
cout << func(75, 12) << endl; // ok
std::cout << std::endl;
}
如果我用一个参数调用Mult
它可以正常工作,因为第二个参数是默认值,但通过指针func
调用它失败了。 func是指向函数的指针,它接受两个整数并返回一个int。
默认的论点是一些C ++语法糖;当使用不充分的参数直接调用函数时,编译器会插入默认值,就像调用者已经显式传递它一样,因此仍然使用完整的参数调用函数(在这种情况下,Mult(4)
被编译为与Mult(4, 2)
相同的代码)。
默认情况下实际上并不是函数类型的一部分,因此您不能使用默认值进行间接调用;语法糖在那里分解,因为一旦你通过指针调用,有关默认值的信息就会丢失。
对于“为什么不”,我推荐你到this answer。如果你想以某种方式保持使用默认的能力,你需要提供的不仅仅是函数指针,例如lamdba会:
auto Double() {
return [](int x,int y=2){ return Mult(x,y); };
}
通过使用可变参数lambda(感谢@Artyer),您甚至不必重复默认值:
#include <iostream>
int Mult(int x, int y = 2) { // y is default
return x * y;
}
auto Double() {
return [](auto... args) { return Mult(args...); };
}
int main(int argc, char* argv[]){
auto func = Double();
std::cout << func(7, 4) << '\n'; // ok
std::cout << func(7) << '\n'; // ok
std::cout << Mult(4) << '\n'; // ok
}
如果你总是将2
作为默认参数,你可以将函数指针包装成一个简单的帮助器类,如下所示:
using pFn_ = int(*)(int, int);
class pFn
{
pFn_ ptr;
public:
pFn(pFn_ p) : ptr(p) {}
int operator()(int x, int y = 2) const {
return ptr(x,y);
}
};
完整的工作示例:https://godbolt.org/z/5r7tZ8