如何通过指向另一个函数返回的函数的指针调用带有默认参数的函数?

问题描述 投票:21回答:3

我有函数Mult, Add, Div, Sub, Mod那些取两个整数并返回其参数的结果。还有一个函数Calc,它将一个字符作为Operator并返回一个指向函数的指针,该函数返回一个整数并获取两个整数参数,如Mult

  • Mult的第二个参数这样的函数是default所以当我调用Calc时,Calc返回MultAdd的地址......取决于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++ function-pointers default-arguments
3个回答
27
投票

默认的论点是一些C ++语法糖;当使用不充分的参数直接调用函数时,编译器会插入默认值,就像调用者已经显式传递它一样,因此仍然使用完整的参数调用函数(在这种情况下,Mult(4)被编译为与Mult(4, 2)相同的代码)。

默认情况下实际上并不是函数类型的一部分,因此您不能使用默认值进行间接调用;语法糖在那里分解,因为一旦你通过指针调用,有关默认值的信息就会丢失。


9
投票

对于“为什么不”,我推荐你到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
}

Live demo


2
投票

如果你总是将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

© www.soinside.com 2019 - 2024. All rights reserved.