class 方法的函数对象

function objects for class methods

我知道当函数不是方法时如何使函数成为输入参数,但当函数时我不知道如何做方法。

这是我尝试过的:

#include <iostream>

class A
{
    void funct_1(int a, void (A::*f)(int))
    {
        (A::*f)(a);
    }

public:

    void funct_2(int k)
    {
        // do something
    }

    void funct_3(int k)
    {
        // do something
    }

    void funct_4(int k)
    {
        // some reason to use the function argument functionality...
        if (k % 2)
            funct_1(k, funct_2);
        else
            funct_1(k, funct_3);
    }
};

int main()
{

    A a;

    a.funct_4(4);

    return 0;
}

以上代码无法编译。我尝试了很多变体,但找不到任何有效的语法用法。 有人可以根据语法解释我在这里做错了什么吗?

指向成员语法的指针总是很难弄清楚。你一直都在,只要把第一个成员函数改成

void funct_1(int a, void (A::*f)(int))
{
    (this->*f)(a);
}

和第四到

void funct_4(int k)
{
    if (k % 2)
        funct_1(k, &A::funct_2);
    else
        funct_1(k, &A::funct_3);
}

对于您最初尝试调用成员函数的尝试,请注意 (A::*f)(a); 在概念上是错误的,因为它没有将成员函数指针 f 实例相关联A。成员函数指针是 class 定义中的偏移量,但并不紧贴 class 的特定实例。这必须在进行实际调用时提供。存在特定的运算符来执行此操作,即 .*->*,如 this->*f。由于它们的优先级较低,您需要添加一组额外的括号:(this->*f).

我不知道你是否需要使用精确的签名,但你不能这样做吗?

template<typename Func>
void funct_1(int a, Func&& func)
{
   std::forward<Func>(func)(a);
}

您的方法的签名没有改变:

void funct_4(int k)
{
    // some reason to use the function argument functionality...
    if (k % 2)
        funct_1(k, funct_2);
    else
        funct_1(k, funct_3);
}

您甚至可以为任意数量的参数扩展它

template<typename Func>
void funct_1(Func&& func, Args&&... args)
{
   std::forward<Func>(func)(std::forward<Args>(args)...);
}

那些允许使用函数作为参数。如果您打算按照您展示的方式在 class 中使用它,它主要是 design-flaw 和 re-think class 结构。

如果您想在 class 中传递成员函数,请将其包含在 lambda 和 std::function 中,因此您可以将其用作变量并使用上述方法。

如果您只是想为您的示例提供一种干净的方式,实际上确实存在一种极端方式:

void funct_1(int a, auto&& func)
{
   (this->*func)(a);
}

所以你的样本变成了

#include <iostream>
#include <functional>

class A
{
    void funct_1(int a, auto&& func)
    {
       (this->*func)(a);
    }
    
public:
    void funct_2(int k)
    {
        std::cout << "func 2" << std::endl;
    }

    void funct_3(int k)
    {
        std::cout << "func 3" << std::endl;
    }

    void funct_4(int k)
    {
        // some reason to use the function argument functionality...
        if (k % 2)
            funct_1(k, &A::funct_2);
        else
            funct_1(k, &A::funct_3);
    }
};

int main()
{
    A a;
    a.funct_4(4);

    return 0;
}

Live demo