std::function 不起作用,但普通的旧函数指针起作用 - 为什么?

std::function does not work, but plain old function pointer does - why?

我想创建一个将 std::function 作为参数的函数,并在内部调用传递的函数:

void handleCollision(std::function<void(const Entity&)>& resolveCollision, const Entity& block) {
    if (playerInRangeOf(block) && playerIntersects(block)) {
        resolveCollision(block);
    }
}

和来电者(在同一个Class内):

for (auto&& block : blocks) {
    handleCollision(resolveCollisionAxisX, block);
}

错误:

Reference to non-static member function must be called
error: no matching function for call to 'StateGame::handleCollision(<unresolved overloaded function type>, Block&)'
handleCollision(resolveCollisionAxisX, block);
                                            ^

但是,如果我跟着C风格的函数指针:

void handleCollision(void (StateGame::*resolveCollision)(const Entity&), const Entity& block) {
    if (playerInRangeOf(block) && playerIntersects(block)) {
        (this->*resolveCollision)(block);
    }
}

然后它确实工作正常(调用者是相同的)。

如何使 std::function 正常工作?旁注:我不想让任何东西静态化。

用 lambda 包起来,替换

handleCollision(resolveCollisionAxisX, block)

[this](const Entity& e){
   this->resolveCollisionAxisX(e);
}

同时将 std::function<void(const Entity&)>& 替换为 std::function<void(const Entity&)>const std::function<void(const Entity&)>&

C++ 成员函数是普通的 C 函数,添加了实例地址作为第一个参数。

例如,编译器的 void StateGame::resolveCollisionAxisX(const Entity&) 等同于 void resolveCollisionAxisX(StateGame* instance, const Entity&)

这里是一个显示工作示例的小代码片段。查看 std::function 模板参数是 void(A*) 而不仅仅是 void().

#include <iostream>

#include <functional>

struct A{
  void foo1(void(A::*resolveCollision)(void)){
    std::cout << "foo [c-style]" << std::endl;
    (this->*resolveCollision)();
  }

  void foo2(std::function<void(A*)> resolveCollision) {
    std::cout << "foo [std::function]" << std::endl;
    resolveCollision(this);
  }

  void target() {
    std::cout << "resolve" << std::endl;
  }

  void caller() {
    std::cout << "caller" << std::endl;
    foo1(&A::target);
    foo2(&A::target);
  }
};

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

如果知道Python,这个概念就更明确了,其实所有的成员函数都有self作为第一个参数(也就是this的分身) C++).