C++ boost::bind 表示无法访问的基类
C++ boost::bind says inaccessible base class
我正在尝试使用boost::bind
来调用类中的成员函数。 通常这工作正常,但在这种特殊情况下,我的编译器 (GCC) 抱怨我试图使用无法访问的基类,而我不是。
下面是一些演示该问题的代码。 我做错了什么?
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
class base
{
protected:
void test()
{
std::cout << "base::test()n";
}
};
class derived: virtual protected base
{
public:
using base::test;
};
int main(void)
{
derived d;
// This works, calling derived::test(), which in turn calls base::test()
d.test();
// This does not work, saying 'base' is an inaccessible base of 'derived',
// but I am not binding base::test, I am binding derived::test.
boost::function<void()> fn;
fn = boost::bind(&derived::test, d);
fn();
return 0;
}
using
声明不定义函数。它"声明一个名称"(不是函数!),并取消隐藏基本名称。确实,声明本身具有自己的可访问性级别,这就是为什么您首先使用它的原因,但要再次强调:using 声明不会声明新的成员函数。例如 C++11 7.3.3/11:
使用声明声明的实体应根据使用声明时的定义在使用它的上下文中已知。
在您的情况下,"它的定义"仍然是void base::test(){}
的,这是派生类已知的实体并由&derived::test
引用。您无法从中获取类型 void(derived:**)()
的函数指针,因为没有这样的函数。
当你说&derived::test
时,使用&
运算符,其工作原理如下(5.3.1/3):
一元
&
运算符的结果是指向其操作数的指针。操作数应为左值或限定 ID。如果操作数是一个限定 id,命名某个C
类m
T
类的非静态成员,则结果的类型为"指向类型T
的类C
的成员的指针",并且是指定 C::m 的 prvalue。
在我对上述逻辑的解释中,&derived::test
"命名类base
的非静态成员test
"。[感谢@DyP:]在 10.2/3 中形式化:
在
C
[...] 中为f
设置的查找由 [...] 声明集 [...] 组成。在声明集中,use-声明由它们指定的成员替换
如果你真的想要,你可以提供一个这样的包装器:
class derived : protected base
{
public:
void test() { base::test(); }
};
(奇怪的是,该解决方案实际上确实隐藏了基本函数,这正是我们想要的。我们没有使用using
,而是使用显式限定名来引用基函数。
调用函数时,需要将隐式this
参数转换为基类。using
声明不会将test
类型从 base::*
调整为 derived::*
。
您可以手动执行此类调整:
static_cast< void (derived::*)() >( &derived::test )
但这同样要求基地是可访问的。因此,完整的解决方案是将上述static_cast
封装在派生类中。否则,它应该是一个可访问的基地。
- 为什么此派生对象无法访问基类的后递减方法?
- 无法访问基类函数 C++
- 相同的层次结构,访问基类的受保护成员时的行为不同
- 如何访问基类向量中的子类变量?(对于实体组件系统)
- 如何从派生类访问基类中的重载运算符?
- 派生类无法访问基类的受保护成员
- 我不能访问基类的函数
- 无法在赋值运算符中访问基类的受保护方法
- 访问基类中直接受保护的字段
- 使用单一实例类作为派生类时,如何访问基类中的函数
- 为什么无法访问基类的函数重载
- 访问基类的受保护成员
- 访问基类C 中的变量
- 尝试访问基类的受保护数据成员时出现编译错误
- 允许从特定派生类访问基类成员
- 如何通过派生类访问基类的受保护成员?
- 在派生的C 类中,访问基类受保护成员作为公共的访问声明
- C++派生类访问基类成员
- 虚函数可以访问基类的友元吗?
- 使用派生模板化类的正确类型转换访问基类中的数据