在这种情况下,我如何std :: bind基类的方法?

时间:2014-04-18 05:45:57

标签: c++ c++11

class animal {
protected:
    animal() {}
    void eat(int x) {}
};


class human
    : private animal
{
public:
    typedef animal base_type;
    using base_type::eat;
};

class stomach {
public:
    stomach(std::function<void(int)> feed) {}
};

class lady
    : public human
{
public:
    typedef lady        this_type;
    typedef human       base_type;

    lady()
        : base_type()
        , m_Stomach(std::bind(&base_type::eat, this, std::placeholders::_1))
    {
    }

private:
    stomach m_Stomach;
};

如果客户端代码写下:

lady gaga;

编译器抱怨std::bind(&base_type::eat, ...) 错误C2064:term不评估为带有2个参数的函数

我发现如果班主任修改为:

class lady
    : public human
{
public:
    typedef lady        this_type;
    typedef human       base_type;

    lady()
        : base_type()
        , m_Stomach(std::bind(&this_type::help_eat, this, std::placeholders::_1))
    {
    }

private:
    void help_eat(int x)
    {
        base_type::eat(x);
    }
    stomach m_Stomach;
};

使用帮助功能,编译器将std::bind好。但代码重复。

我还发现如果将std::bind更改为lambda m_Stomach([&](int x){ base_type::eat(x); }),也可以编译。

我的问题是,在这种情况下使用std::bind是否有更好的方法?如果没有,我可能会考虑lambda。

2 个答案:

答案 0 :(得分:2)

您的问题是animal私有基类human,因此传递(并存储)this(类型为{{1} }})不能用于从lady*调用方法。您可以修复它,使其成为公共基础或向animal添加方法:

human

以后绑定:

animal* animal_ptr() { return this; }

Live example

答案 1 :(得分:0)

动物是人类的私人基类,虽然使用声明使得函数可用,但它不会改变函数的签名void (animal::*)(int)

从7.3.3使用声明

  

为了重载解析,其功能是   由using声明引入派生类将被处理   好像他们是派生类的成员。特别是   隐式此参数应被视为指向它的指针   派生类而不是基类。 这对此没有影响   函数的类型,以及所有其他方面的函数   仍然是基类的成员。

因此,绑定(指代函数类型)会导致错误‘animal’ is an inaccessible base of ‘lady’(g ++)。

您可以使用lambda m_Stomach([this](int x) { this->eat(x); })修复它, 用void eat(int x) { base_type::eat(x); }代替人类的使用声明,或者按照你的方式去做。