C ++:使用函数指针时未解决的重载函数

时间:2012-05-04 19:01:15

标签: c++ function-pointers

#include <iostream>
using namespace std;

class B
{
public:
  int getMsg(int i)
  {
    return i + 1;
  }
};

class A
{
  B b;
public:
  void run()
  {
    taunt(b.getMsg);
  }

  void taunt(int (*msg)(int))
  {
    cout << (*msg)(1) << endl;
  }
};

int main()
{
  A a;
  a.run();
}

上面的代码在A类中有一个B类,而A类有一个方法taunt,它将一个函数作为参数。 B类的getMsg被传递到taunt ...上面的代码生成了以下错误消息:“错误:没有匹配函数来调用'A :: taunt()'”

上述代码中导致错误消息的原因是什么?我错过了什么吗?

更新

#include <iostream>
using namespace std;

class B
{
public:
  int getMsg(int i)
  {
    return i + 1;
  }
};

class A
{
  B b;
public:
  void run()
  {
    taunt(b.getMsg);
  }

  void taunt(int (B::*msg)(int))
  {
    cout << (*msg)(1) << endl;
  }
};

int main()
{
  A a;
  a.run();
}

t.cpp:在成员函数'void A :: run()'中: 第19行:错误:没有匹配函数来调用'A :: taunt()' 由于-Wfatal-errors而导致编译终止。

将(* msg)(int)更改为(B :: * msg)(int)之后我仍然得到相同的错误

3 个答案:

答案 0 :(得分:2)

b.getMsg不是形成指向成员的指针的正确方法,您需要&B::getMsg

(*msg)(1)不是通过指向成员的指针调用函数的正确方法,您需要指定一个对象来调用该函数,例如: (使用临时的)(B().*msg)(1)

答案 1 :(得分:0)

在OOP中执行此类操作的正确方法是使用接口,因此您需要做的就是定义一个接口并在B类中实现它之后,将实现此接口的实例的指针传递给A类中的方法

class IB{
public:
 virtual void doSomething()=0;
};

class B: public IB{
public:
 virtual void doSomething(){...}
};

class A{
public:
 void doSomethingWithB(IB* b){b->doSomething();}
};

答案 2 :(得分:0)

这适用于VS 2010.所有行的输出都相同:

#include <iostream>
#include <memory>
#include <functional>

using namespace std;
using namespace std::placeholders;

class A
{
public:
    int foo(int a, float b)
    {
        return int(a*b);
    }
};

int main(int argc, char* argv[])
{
    A temp;

    int x = 5;
    float y = 3.5;

    auto a = std::mem_fn(&A::foo);
    cout << a(&temp, x, y) << endl;

    auto b = std::bind(a, &temp, x, y);
    cout << b() << endl;

    auto c = std::bind(std::mem_fn(&A::foo), &temp, _1, y);
    cout << c(5) << endl;
}

基本上,您使用std::mem_fn来获取成员函数的可调用对象,然后使用std::bind来绑定其他参数,包括对象指针本身。我很确定如果您愿意,也可以使用std::ref来封装对象的引用。我还包括_1转发标记只是为了另一种方式来指定绑定中的一些参数,而不是其他参数。你甚至可以指定类实例的所有内容,如果你想要所有相同的参数,但让它适用于不同的对象。由你决定。

如果您更愿意使用boost::bind,它会识别成员函数,您可以将它全部放在一行上稍微缩短一点:auto e = boost::bind(&A::foo, &temp, x, y)但显然完全使用它并不多std C ++ 11调用。