提问者:小点点

如何将方法作为参数传递给其他方法?


我有两个有方法的类:

void ClassA::myFunction(void (*fn)() = NULL);
void ClassB::run();

和一些代码

ClassA A();
ClassB B();

void runBfn()
{
  B.run();
}

void setup()
{
  A.myFunction( runBFn ); // works
  A.myFunction( [](void){B.run();} ); // works
  A.myFunction( B.run ); // not works
}

为什么a.myfunction(b.run);不能工作? 我能使它不声明单独的函数(匿名或不)吗?


共3个答案

匿名用户

myFunction()采用指向独立函数的指针,而不是指向类方法的指针。 非捕获lambda可以隐式地转换为函数指针。

您需要:

  1. 添加接受方法指针的MyFunction()重载:
class ClassB;

class ClassA {
public:
    void myFunction(void (*fn)());
    void myFunction(B &b, void (B::*fn)());
};

class ClassB {
public:
    void run();
};
void ClassA::myFunction(void (*fn)()) {
    fn();
}

void ClassA::myFunction(B &b, void (B::*fn)()) {
    (b.*fn)();
}

void ClassB::run() {
    ...
}
ClassA A;
ClassB B;

void runBfn() { B.run(); }

void setup() {
    A.myFunction( runBFn );
    A.myFunction( [](){ B.run(); } );
    A.myFunction( B, &ClassB::run );
}
class Runnable {
public:
    virtual void run() = 0;
};

class ClassA {
public:
    void myFunction(void (*fn)());
    void myFunction(Runnable &r);
};

class ClassB : public Runnable {
public:
    void run() override;
};
void ClassA::myFunction(void (*fn)()) {
    fn();
}

void ClassA::myFunction(Runnable &r) {
    r.run();
}

void ClassB::run() {
    ...
}
ClassA A;
ClassB B;

void runBfn() { B.run(); }

void setup() {
    A.myFunction( runBFn );
    A.myFunction( [](){ B.run(); } );
    A.myFunction( B );
}
#include <functional>

class ClassA {
public:
    void myFunction(std::function<void()> fn);
};

class ClassB {
public:
    void run();
};
void ClassA::myFunction(std::function<void()> fn) {
    fn();
}

void ClassB::run() {
    ...
}
ClassA A;
ClassB B;

void runBfn() { B.run(); }

void setup() {
    A.myFunction( runBFn );
    A.myFunction( [](){ B.run(); } );
    auto fn = std::bind(&ClassB::run, &B);
    A.myFunction( fn );
}
class ClassA {
public:
    template<typename Callable>
    void myFunction(Callable fn) {
        fn();
    }
};

class ClassB {
public:
    void run();
};
void ClassB::run() {
    ...
}
ClassA A;
ClassB B;

void runBfn() { B.run(); }

void setup() {
    A.myFunction( runBFn );
    A.myFunction( [](){ B.run(); } );
    auto fn = std::bind(&ClassB::run, &B);
    A.myFunction( fn );
}

匿名用户

您需要更改函数签名:

void myFunction2(void (ClassB::*run)(void), ClassB& b){}

然后叫它用:

A.myFunction2( &ClassB::run, B);

生活在天赐之地。

PS。

这些不是对象而是函数:

ClassA A();
ClassB B();

您可以改用以下方式:

ClassA A{};
ClassB B{};

匿名用户

这是因为成员函数签名是void(classb::*)()

但您希望作为参数void(*)()

我建议您使用std::function:

#include <functional>
#include <iostream>

class ClassB
{
public:
    void print(std::string str) {
        std::cout << str << std::endl;
    }
};

void test_foo(std::function<void(std::string)> foo)
{
    foo("Hello");
}

int main (int argc, const char * argv[])
{
    //...

    ClassB b;
    auto print_f = std::bind(&ClassB::print, b, std::placeholders::_1);
    test_foo(print_f);

    return 0;
}