的std ::绑定() - 从派生的类的成员函数荷兰国际集团的基保护的成员函数(std::bind(

2019-07-18 16:05发布

我想bind()从派生类到我的基类的版本的功能。 该功能被标记为基础的保护。 当我这样做,代码简单地在编译锵(苹果LLVM编译器4.1),但给出了一个错误都G ++ 4.7.2和Visual Studio 2010中的错误是沿着线:“'基地:: foo的:不能访问受保护的成员“。

其含义是,对于参考上下文实际上是内bind()其中受保护的过程的功能被看见。 但不应bind()继承调用函数的情况下-在这种情况下, Derived::foo() -并且因此看到基础的方法访问?

下面的程序说明问题。

struct Base
{
protected: virtual void foo() {}
};

struct Derived : public Base
{
protected:
    virtual void foo() override
    {
        Base::foo();                        // Legal

        auto fn = std::bind( &Derived::foo, 
            std::placeholders::_1 );        // Legal but unwanted.
        fn( this );

        auto fn2 = std::bind( &Base::foo, 
            std::placeholders::_1 );        // ILLEGAL in G++ 4.7.2 and VS2010.
        fn2( this );
    }
};

为什么行为的差异? 哪个是对的? 什么可行的解决方法的错误,让编译器?

Answer 1:

答:看到的boost ::与保护成员和背景结合它引用的是这部分标准

当一个非静态数据成员或非静态成员函数是其命名类的受保护构件超出第11节中先前描述的附加的访问检查施加(11.2)105)如上所述,访问受保护成员被准许,因为参考发生于某些类C的朋友或构件如果访问是要形成一个指向构件(5.3.1),所述嵌套名称说明符应名称C或从C派生的类的所有其他的访问涉及(可能隐含的)对象表达式(5.2.5)。 在这种情况下,该对象的类别的表达应是C或从C派生的类

解决方法:使foo一个public成员函数

#include <functional>

struct Base
{
public: virtual void foo() {}
};


Answer 2:

这有没有关系bind 。 因为一块标准的@rhalbersma已经引述,表达&Base::foo是在一个非friended构件非法Derived ,在每个上下文中。

但是,如果你的目的是为了做一些等同于调用Base::foo(); ,你有一个更大的问题:指向成员函数始终调用虚拟覆盖。

#include <iostream>

class B {
public:
    virtual void f() { std::cout << "B::f" << std::endl; }
};

class D : public B {
public:
    virtual void f() { std::cout << "D::f" << std::endl; }
};

int main() {
    D d;
    d.B::f();   // Prints B::f

    void (B::*ptr)() = &B::f;
    (d.*ptr)(); // Prints D::f!
}


文章来源: std::bind()-ing a base protected member function from a derived class's member function