C ++ boost :: bind表示无法访问的基类

时间:2013-10-12 23:18:07

标签: c++ inheritance boost

我正在尝试使用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;
}

2 个答案:

答案 0 :(得分:7)

using声明未定义函数。它“声明一个名称”(不是函数!),并取消隐藏基本名称。确实,声明本身具有自己的可访问性级别,这就是您首先使用它的原因,但再次强调:using声明不会声明新的成员函数。例如。 C ++ 11 7.3.3 / 11:

  

using-declaration 声明的实体应在上下文中根据using-declaration点的定义使用它。

“它的定义”,在您的情况下,仍为void base::test(){},而 是派生类已知并由&derived::test引用的实体。你不能从中获得类型void(derived:**)()的函数指针,因为没有这样的函数。

当您说&derived::test时,会使用& - 运算符,其工作原理如下(5.3.1 / 3):

  

一元&运算符的结果是指向其操作数的指针。操作数应为左值或 qualified-id 。如果操作数是 qualified-id ,则命名类型为m的某个类C的非静态成员T,结果的类型为“指向成员的指针C类的T类,并且是指定C :: m的prvalue。

在我对上述逻辑的解释中,&derived::test“命名类test的非静态成员base”。 [感谢@DyP:]在10.2 / 3中正式化:

  

f [...]中C的查找集包含[...]声明集[...]。在声明集中, using-declarations 由他们指定的成员替换

如果你真的想要,你可以提供这样的包装:

class derived : protected base
{
public:
    void test() { base::test(); }
};

(奇怪的是,该解决方案实际上 隐藏了基本功能,这是我们想要的。我们使用显式限定名称来引用基本功能,而不是使用using。 )

答案 1 :(得分:6)

调用函数时,需要将隐式this参数转换为基类。 using声明不会将test的类型从base::*调整为derived::*

您可以手动执行此类调整:

static_cast< void (derived::*)() >( &derived::test )

但这同样要求基地可以访问。因此,完整的解决方案是将上述static_cast封装在派生类中。否则它应该是一个可访问的基础。