Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::bind()-从派生类';s成员函数_C++_C++11_Protected_Derived Class_Stdbind - Fatal编程技术网

C++ std::bind()-从派生类';s成员函数

C++ std::bind()-从派生类';s成员函数,c++,c++11,protected,derived-class,stdbind,C++,C++11,Protected,Derived Class,Stdbind,我想从派生类将()绑定到我的基类版本的函数。该功能在底座中标记为受保护。当我这样做时,代码在Clang(Apple LLVM Compiler 4.1)中编译得很愉快,但在g++4.7.2和Visual Studio 2010中都出现了错误。错误大致如下:“'Base::foo':无法访问受保护的成员。” 这意味着引用的上下文实际上在bind()中,其中函数当然被视为受保护的。但是bind()是否应该继承调用函数的上下文(在本例中是Derived::foo()),从而将基方法视为可访问的 以下程

我想从派生类将()绑定到我的基类版本的函数。该功能在底座中标记为受保护。当我这样做时,代码在Clang(Apple LLVM Compiler 4.1)中编译得很愉快,但在g++4.7.2和Visual Studio 2010中都出现了错误。错误大致如下:“'Base::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 );
    }
};
为什么行为上存在差异?哪个是正确的?给出错误的编译器有什么解决方法?

回答:请参阅标准中引用的这一部分

除第11条前面所述之外的额外访问检查 当非静态数据成员或非静态成员函数 是其命名类(11.2)105)的受保护成员,如所述 在此之前,由于引用 发生在某个C类的朋友或成员中。如果要访问窗体 一个指向构件(5.3.1)的指针,嵌套名称说明符应命名为C或 从C派生的类。所有其他访问都涉及 隐式)对象表达式(5.2.5)。在本例中 对象表达式应为C或从C派生的类

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

#include <functional>

struct Base
{
public: virtual void foo() {}
};
#包括
结构基
{
public:virtualvoid foo(){}
};

这与
bind
无关。由于已经引用了标准@rhalbersma,因此在任何上下文中,
&Base::foo
表达式在
派生的
的非友好成员中都是非法的

但是如果您的目的是做一些与调用
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!
}
#包括
B类{
公众:

虚拟void f(){std::cout
Derived::foo
调用自身是故意的,还是仅仅是简化为一个例子的结果?@aschepler这是“legal but underfect”中“不需要的”部分。如果您不能更改
Base
,请使用派生方法(例如,
void basefoo(){Base::foo();}
)令人惊讶和困惑地在VisualC++(Express 2010)中,你可以使用<代码>和派生::Boo::Foo绕过这个错误,但是它基本上忽略了你的第二个参数(即它总是使用<代码>这个/<代码>)。