【问题标题】:Binding to privately inherited member function绑定到私有继承的成员函数
【发布时间】:2016-07-15 18:15:19
【问题描述】:

我想 std::bind 到来自私有基类的成员函数,在派生类中使用 using-声明“公开”。直接调用函数有效,但似乎绑定或使用成员函数指针无法编译:

#include <functional>

struct Base {
    void foo() { }
};

struct Derived : private Base { 
    using Base::foo;            
};

int main(int, char **)
{
    Derived d;

    // call member function directly:
    // compiles fine
    d.foo();

    // call function object bound to member function:
    // no matching function for call to object of type '__bind<void (Base::*)(), Derived &>'
    std::bind(&Derived::foo, d)();

    // call via pointer to member function:
    // cannot cast 'Derived' to its private base class 'Base'
    (d.*(&Derived::foo))();

    return 0;
}

查看上面的错误信息,问题似乎是Derived::foo 仍然只是Base::foo,我无法在Derived 本身之外通过Derived 访问Base

这似乎不一致 - 我应该不能互换使用直接调用、绑定函数和函数指针吗?

是否有一种解决方法可以让我绑定到Derived 对象上的foo,最好不更改BaseDerived(在我不拥有的库中)?

【问题讨论】:

  • 作为一种(有点难看的)解决方法,您可以使用 lambda [&amp;d] () { d.foo(); }

标签: c++ stdbind private-inheritance


【解决方案1】:

这里的问题是 using-declaration 的实际作用:

struct Derived : private Base { 
    using Base::foo;            
};

这会将Base::foo 带入Derived 的公共范围,但它不会创建一个全新的函数。 等于写过:

struct Derived : private Base {
    void foo() { Base::foo(); }
}

仍然只有Base::foo()using-declaration 只会影响访问规则和重载解析规则。因此&amp;Derived::foo 确实具有void (Base::*)() 类型(而不是void (Derived::*)()!),因为这是唯一存在的foo。由于Baseprivate,因此通过指向Base 的指针访问成员是不正确的。我同意这是非常不幸的(“不一致”是个好词)。

您仍然可以创建调用foo 的函数对象。您只是不能使用指向成员的指针。使用 C++14,如果冗长,这将变得很简单(我在这里假设任意参数,void foo() 只是问题的简化):

auto d_foo = [d](auto&&... args){ return d.foo(std::forward<decltype(args)>(args)...); }

使用 C++11,您必须使用可变参数模板 operator() 编写类型。

【讨论】:

  • 很好,使用 lambdas 是一种避免指针的有趣方式!有没有不需要 C++11 的解决方法?
  • @AndersJohansson 你已经在使用std::bind?无论如何,任何 lambda 总是可以写成等效结构 struct D_Foo { D d; void operator()() { d.foo(); } };
  • 我的测试用例是 C++11 和 std::bind 但在生产中我仅限于 C++03 和 boost::bind - 我保持问题简单,因为错误是相同的。听起来像上面这样的结构应该可以解决问题。谢谢!
猜你喜欢
  • 2020-09-04
  • 2020-09-01
  • 2018-05-11
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 2013-02-12
  • 2015-01-21
相关资源
最近更新 更多