C ++使用指针绑定成员函数

时间:2016-05-19 14:04:30

标签: c++ c++11 stdbind

我试图理解std :: bind如何与成员函数指针一起工作。所以这个例子对我来说很清楚。

#include<iostream>
#include<functional>

using namespace std::placeholders;

struct Foo 
{
    void print_sum(int n1, int n2)
    {
        std::cout << n1+n2 << '\n';
    }
};


int main()
{    
    Foo foo;
    auto f3 = std::bind(&Foo::print_sum, &foo, 95, _1);
    f3(5); //prints 100
    return 0;
}

_1替换为5并且函数被调用,因为我期望它。

看另一个例子,它结合了一个成员函数和来自Effective C ++的std :: function。

#include<iostream>
#include<functional>

using namespace std::placeholders;

class GameCharacter; // forward declaration

int defaultHealthCalc(const GameCharacter& gc) 
{
    std::cout<<"Calling default function";
    return 10;
}

class GameCharacter
{ 
public:
    typedef std::function<int (const GameCharacter&)> HealthCalcFunc; 
    explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)  :healthFunc(hcf){} // constructor
    void setHealthFunction(HealthCalcFunc hcf)
    { 
        healthFunc = hcf;
    }

    int healthValue() const 
    { 
        return healthFunc(*this);
    }
private:
    HealthCalcFunc healthFunc; // pointer to function
};

class EvilBadGuy : public GameCharacter{
public:
    explicit EvilBadGuy(HealthCalcFunc hcf = defaultHealthCalc) : GameCharacter(hcf) {} // constructor
};

class GameLevel{
public:
    GameLevel(int l = 1) : level(l){}
    int health(const GameCharacter& gc) const   
    {
        std::cout<<"Calling gamelevel health"<<std::endl;
        return level * 10000;
    }
    void setLevel(int l) {
        level = l;
    }
private:
    int level;
};

int main()
{    
    GameLevel currentLevel; // default construct 
    EvilBadGuy ebg3(std::bind(&GameLevel::health, std::cref(currentLevel),_1)); // what is _1 here ?
    std::cout << ebg3.healthValue() << std::endl;

    return 0;
}

我的主要困惑在于上面的占位符_1。有人可以帮我解决这个问题吗?在上面的例子中,_1是调用函数时传递给它的值,但我不明白在创建对象时如何解决这个问题。

感谢。

1 个答案:

答案 0 :(得分:1)

_1 ... _N是占位符(因为它们位于std ::占位符中非常明显。 你通过使用它们来做的是告诉哪个参数用于哪个函数参数。

SomeClasss obj;
auto f1 = std::bind(&SomeClass::SomeFunction, &obj, _1, _2);

这意味着当调用SomeClass :: SomeFunction时,f1的第一个参数将用作第一个参数,而f1的第二个参数将用作第二个参数。 你也可以做像

这样的事情
SomeClass obj;
auto f2 = std::bind(&SomeClass::SomeFunction, &obj, _2, _1);

现在f2的第一个参数是第二个参数,第二个参数是调用SomeClass :: SomeFunction时的第一个参数。

那你用

做什么
EvilBadGuy ebg3(std::bind(&GameLevel::health, std::cref(currentLevel),_1))

是在对象currentLevel上使用其healthFunc beeing GameLevel :: health来构造和EvilBadGuy对象。 healthFunc的第一个参数将是传递给GameLevel :: health的第一个参数。