std::bind()-ing 从派生类的成员函数中获取受保护的基本成员函数
std::bind()-ing a base protected member function from a derived class's member function
我想从派生类中bind()
到我的基类版本的函数。该函数在底座中标记为受保护。当我这样做时,代码在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 );
}
};
为什么会有行为差异?哪个是正确的?对于出错的编译器,有哪些解决方法?
答案:参见 boost::bind with protected members & context,其中引用了标准的这一部分
超出前面第 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() {}
};
bind
无关。 由于已经引用的标准@rhalbersma部分,表达&Base::foo
在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!
}
- 如何使用指针传递给函数的数组中对象的函数成员
- c++构造函数成员初始化:传递参数
- 创建 std::函数,它返回具有函数成员值的变量.分段错误
- 如何在C++通过公共函数访问私有函数成员?
- 解释了构造函数成员初始化列表
- 调用std::函数成员时内存损坏
- 是否可以为模板类的模板函数成员设置别名?
- 捕获 lambda 函数C++成员变量
- 构造函数成员初始值设定项跨成员列出,安全吗?
- 获取与在模板参数中传递的函数成员类型相同的类
- 如何从公共函数成员访问地图私有成员
- C 构造函数成员分配优化
- 使用命名空间进行函数成员定义
- 函数成员作为 CUDA 内核的参数
- 模板基类函数成员的别名
- 函数成员中用于void和继承的enable_if
- 头文件中是否定义了一个很长的Class函数成员
- 类内/构造函数成员初始化
- 使用指向部分专用函数成员的指针自动填充向量
- 指向函数成员的指针