将一类方法的指针存储到另一类

时间:2018-09-28 00:49:33

标签: c++ boost

我有一个类A,它具有方法void fun(int, int)void fun1(int, int)。这些是非静态方法。

struct A {
    void fun(int,int){}
    void fun1(int,int){}
};

现在在类B中,我想存储指向方法之一的指针。

这意味着object1的{​​{1}}将具有指向B的指针,而fun的{​​{1}}将具有指向object2的指针。

现在,我的B和指向处理程序的指针必须是通用的。

一种方法是使用函数指针。 这样我就可以使用fun1来存储set_handler()void(A::*pointer)(int,int)的地址。

fun

我一直在寻找fun1,但它需要特定的名称。我在这里如何使用升压?

1 个答案:

答案 0 :(得分:1)

我将您的问题推广到了实际上使用指针执行某些操作的代码中-因此我们知道何时实现了目标:

Live On Coliru

#include <iostream>

struct A {
    void fun(int  a, int b) { std::cout << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
    void fun1(int a, int b) { std::cout << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
};

struct B {
    typedef void (A::*pointer)(int, int);
    pointer f;

    void set_handler(pointer p) { f = p; }

    void run(A& instance) {
        (instance.*f)(42, 42);
    }
};

int main() {
    B object1;
    B object2;
    object1.set_handler(&A::fun);
    object2.set_handler(&A::fun1);

    A a;
    object1.run(a);
    object2.run(a);
}

打印

fun(42,42)
fun1(42,42)

使用boost::functionstd::function

您必须允许使用实例参数(隐式this参数):

Live On Coliru

struct B {
    using function = std::function<void(A&, int, int)>;
    function f;

    void set_handler(function p) { f = p; }

    void run(A& instance) {
        f(instance, 42, 42);
    }
};

输出相同的输出。当然,您可以像使用boost::functionboost::bind一样

那绑定呢?

当您要适应功能签名时,

绑定就会出现。因此,例如您想绑定到A&的任何实例,而无需实际将其传递到run()

Live On Coliru

#include <iostream>
#include <functional>

struct A {
    std::string name;
    void fun(int  a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
    void fun1(int a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
};

struct B {
    using function = std::function<void(int, int)>;
    function f;

    void set_handler(function p) { f = p; }

    void run() {
        f(42, 42);
    }
};

int main() {
    B object1;
    B object2;
    A a1 {"black"};
    A a2 {"white"};

    {
        using namespace std::placeholders;
        object1.set_handler(std::bind(&A::fun, &a1, _1, _2));
        object2.set_handler(std::bind(&A::fun1, &a2, _1, _2));
    }

    object1.run();
    object2.run();
}

哪些印刷品:

name:black fun(42,42)
name:white fun1(42,42)

更多美好

在c ++中,您可以不使用bind及其讨厌的占位符(还有其他警告,例如按值存储所有参数的bind)。相反,您可以使用lambda:

Live On Coliru

#include <iostream>
#include <functional>

struct A {
    std::string name;
    void fun(int  a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
    void fun1(int a, int b) { std::cout << "name:" << name << " " << __FUNCTION__ << "(" << a << "," << b << ")" << std::endl; }
};

struct B {
    using function = std::function<void(int, int)>;
    function f;

    void set_handler(function p) { f = p; }

    void run() {
        f(42, 42);
    }
};

int main() {
    B object1;
    B object2;

    object1.set_handler([](int a, int b) {
            A local_instance {"local"};
            local_instance.fun(a*2, b*3); // can even do extra logic here
        });

    A main_instance {"main"};
    object2.set_handler([&main_instance](int a, int b) {
            main_instance.fun1(a, b); // can even do extra logic here
        });

    object1.run();
    object2.run();
}

打印

name:local fun(84,126)
name:main fun1(42,42)