当前位置: 首页 > 知识库问答 >
问题:

将成员函数指针的向量传递给函数

云英才
2023-03-14

我编写了一个代码来传递函数指针列表(按其名称)作为参数。但我有错误。你能解释为什么我在做地图时有错误吗?

#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <map>

class Foo
{
public:
    void foo(int a, int b)
    {
        std::cout << a <<" "<< b<<'\n';
    }
};

class Bar
{
public:
    void bar(int a, int b)
    {
        std::cout << a<<" "<< b << '\n';
    }
};


int main()
{

    Foo foo;
    Bar bar;
    std::map<std::string,  void (*)(int,int)>myMap;
    myMap["bar"] = &Bar::bar;
    myMap["foo"] = &Foo::foo;

    std::vector<std::function<void (int )>> listofName;
    std::string s1("bar");
    std::string s2("foo");

    listofName.push_back(bind(myMap[s1],&bar,std::placeholders::_1,1));
    listofName.push_back(bind(myMap[s2],&foo,std::placeholders::_1,3));

    for (auto f : listofName) {
        f(2);
    }

 return 0;
}

错误:

34:18:错误:无法将'void(Bar::)(int, int)'转换为'std::map, void(*)(int, int)

35:18:错误:无法将“无效(foo::)(整数,整数)”转换为“标准::映射,无效(*)(整数,整型)

41:70:错误:没有用于调用“std::vector”的匹配函数

共有3个答案

仇征
2023-03-14

成员函数包含指向this的隐藏指针。一种古老的技术(继承自C)是将成员函数包装在一个静态函数中,该函数采用指向对象的指针。这里的好处是,由于可以安全地将任何指针强制转换为void*,因此可以告诉静态包装器它的第一个参数是void*,并将其强制转换为正确的对象指针以使用它。当然,如果你传递一个指向不同对象的指针,你会得到未定义的行为。但它只需要对原始代码进行最小的更改:

#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <map>

class Foo
{
public:
    void foo(int a, int b)
    {
        std::cout << a <<" "<< b<<'\n';
    }
    static void doFoo(void *obj, int a, int b) { // the wrapper
        static_cast<Foo *>(obj)->foo(a, b);
    }
};

class Bar
{
public:
    void bar(int a, int b)
    {
        std::cout << a<<" "<< b << '\n';
    }
    static void doBar(void *obj, int a, int b) { // wrapper again
        static_cast<Bar *>(obj)->bar(a, b);
    }
};


using std::bind;

int main()
{

    Foo foo;
    Bar bar;
    // function will take an additional void *
    std::map<std::string,  void (*)(void*, int,int)>myMap;
    myMap["bar"] = &Bar::doBar;
    myMap["foo"] = &Foo::doFoo;

    std::vector<std::function<void (int )>> listofName;
    std::string s1("bar");
    std::string s2("foo");

    listofName.push_back(bind(myMap[s1],(void *)&bar,std::placeholders::_1,1));
    listofName.push_back(bind(myMap[s2],(void *)&foo,std::placeholders::_1,3));

    for (auto f : listofName) {
        f(2);
    }

 return 0;
}

这样,它编译得很好(在C 11模式下),并按预期给出:

2 1
2 3

师增
2023-03-14

不能在这样的映射中存储成员函数指针:

std::map<std::string,  void (*)(int,int)>myMap;

您必须将其更改为:

std::map<std::string,  void (Foo::*)(int,int)>myMap;

但是你只能存储指向Foo类成员的指针。所以最好的选择是在这里使用d::f。下面是一个工作代码:

直播

#include <functional>
#include <iostream>
#include <string>
#include <vector>
#include <map>

class Foo
{
public:
    void foo(int a, int b)
    {
        std::cout << a <<" "<< b<<'\n';
    }
};

class Bar
{
public:
    void bar(int a, int b)
    {
        std::cout << a<<" "<< b << '\n';
    }
};


int main()
{

    Foo foo;
    Bar bar;
    using namespace std::placeholders;
    std::map<std::string,  std::function<void (int,int)>>myMap;
    myMap["bar"] = std::bind(&Bar::bar, &bar, _1, _2);
    myMap["foo"] = std::bind(&Foo::foo, &foo, _1, _2);

    std::vector<std::function<void (int )>> listofName;
    std::string s1("bar");
    std::string s2("foo");

    listofName.push_back(bind(myMap[s1], std::placeholders::_1, 1));
    listofName.push_back(bind(myMap[s2], std::placeholders::_1, 3));

    for (auto f : listofName) {
        f(2);
    }

 return 0;
}
公孙宏畅
2023-03-14

成员函数需要知道它们是哪个对象的成员,这样它们才能对正确的< code>this进行操作。

因此,您需要确保存储在map中的函数知道它将来是哪个对象的成员。

int main() {
  using namespace std::placeholders;
  Foo foo;
  Bar bar;
  std::map<std::string, std::function<void(int, int)>> myMap;
  myMap["bar"] = std::bind(&Bar::bar, &bar, _1, _2);
  myMap["foo"] = std::bind(&Foo::foo, &foo, _1, _2);

稍后,它已经知道它是哪个对象的成员,你不需要再告诉它了:

  // ..
  listofName.push_back(std::bind(myMap[s1], _1, 1));
  listofName.push_back(std::bind(myMap[s2], _1, 3));
 类似资料:
  • C++ 指针 C++ 允许您传递指针给函数,只需要简单地声明函数参数为指针类型即可。 下面的实例中,我们传递一个无符号的 long 型指针给函数,并在函数内改变这个值: #include <iostream> #include <ctime> using namespace std; void getSeconds(unsigned long *par); int main () {

  • 我正在尝试将参数传递给作为参数传递的函数指针。 代码: 我得到了这个错误: 类型"void"的参数与类型"void(*)(wchar_t*,wchar_t*)"的参数不兼容 如何解决此问题以完成我想要实现的目标? 编辑:对不起,不清楚。我实际上试图完成的是将函数注入子进程并传递两个参数(wchar_t*、wchar_t*),以便我可以使用它们。但主函数可以是void或int argc、char**

  • 我正在尝试设置一个“事件接收器”类,将GLFW回调封装到用户可以从中继承的类中,但在将基类成员函数传递到GLFW“set callback”函数中时遇到问题。 这本质上提供了一个带有纯虚拟函数的基类,供用户继承和重写,以便在事件发生时提供自己的逻辑。用户定义的子类将被传递到更大的“应用程序框架”类中,该类将进行必要的调用以设置GLFW回调函数。 当然,您不能将成员函数作为函数参数传递,因为您必须提

  • C ++允许您传递指向函数的指针。 为此,只需将函数参数声明为指针类型即可。 下面是一个简单的例子,我们将一个无符号长指针传递给一个函数并更改函数内部的值,该函数反映在调用函数中 - #include <iostream> #include <ctime> using namespace std; void getSeconds(unsigned long *par); int main () {

  • FAQs in section [33]: [33.1] “成员函数指针”类型不同于“函数指针”吗? [33.2] 如何将一个成员函数指针传递到信号处理函数,X事件回调函数,系统调用来启动一个线程/任务等? [33.3] 为什么我总是收到编译错误(类型不匹配)当我尝试用一个成员函数作为中断服务例程? when I try to use a member function as an interru

  • 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似。我们可以把函数的这个首地址(或称入口地址)赋予一个 指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就是 函数指针。 函数指针的定义形式为: returnType (*pointerName)(param list); returnType