为什么不能在一个lambda使用私有方法?(Why is it not possible to us

2019-06-27 00:36发布

有这样一类:

class A {
public:
    bool hasGrandChild() const;

private:
    bool hasChild() const;
    vector<A> children_;
};

为什么不能使用的私有方法hasChild()在lambda表达式的方法定义hasGrandChild()这样的吗?

bool A::hasGrandChild() const {
    return any_of(children_.begin(), children_.end(), [](A const &a) {
        return a.hasChild();
    });
}

编译器会发出一个错误的方法hasChild()是在范围内的私人。 有没有什么解决方法吗?

编辑:看来,代码我张贴它最初的作品。 我认为这是相当的,但该代码不会对海湾合作委员会的工作更像是这样的:

#include <vector>
#include <algorithm>

class Foo;

class BaseA {
protected:
    bool hasChild() const { return !children_.empty(); }
    std::vector<Foo> children_;
};

class BaseB {
protected:
    bool hasChild() const { return false; }
};

class Foo : public BaseA, public BaseB {
public:
  bool hasGrandChild() const {
    return std::any_of(children_.begin(), children_.end(), [](Foo const &foo) {
        return foo.BaseA::hasChild();
      });
  }  
};

int main()
{
  Foo foo;
  foo.hasGrandChild();
  return 0;
}

似乎有与完全合格的名字是一个问题, 这是行不通的,但这个工程 。

Answer 1:

这似乎只是在特殊情况下,海湾合作委员会的错误,当拉姆达试图访问从父类中使用完全合格的名称保护成员。 这不起作用 :

class Base {
protected:
    bool hasChild() const { return !childs_.empty(); }
    std::vector<Foo> childs_;
};

class Foo : public Base {
public:
  bool hasGrandChild() const {
    return std::any_of(childs_.begin(), childs_.end(), [](Foo const &foo) {
      return foo.Base::hasChild();
    });
  }  
};

但这个工程 :

class Foo : public Base {
public:
  bool hasGrandChild() const {
    return std::any_of(childs_.begin(), childs_.end(), [](Foo const &foo) {
      return foo.hasChild();
    });
  }  
};

据C ++ 11,5.1.2 / 3:

类型的λ-表达的(也是封闭的对象的类型)是一个独特的,无名不愈合类类型 - 称为闭合类型 - 其特性如下所述。 这个类型不是汇总(8.5.1)。 封闭件类型是在最小的块范围,类范围,或命名空间中包含对应λ-表达范围中声明

然后C ++ 11,11.7 / 1:

嵌套类是一个部件,因此具有相同的访问权限的任何其它构件。

因此,提到的功能,局部拉姆达应该具有相同的访问权限之类的任何其他成员。 因此,它应该能够调用从父类保护方法。



Answer 2:

标准(C ++ 11,§5.1.2/ 3)指出

类型的λ-表达的(也是封闭的对象的类型)是一个独特的,无名不愈合类类型-称为闭合类型

因为它是不是一个独特的类类型friendA ,它并没有获得A的私有成员。

什么编译器这里是创建具有适当的成员来存储任何捕获变量,适当的类类型operator()等-这正是你会写自己,如果你想效仿在C ++ 03 lambda表达式。 这种类型的肯定不能访问private成员,这可能更容易想象为什么限制存在,为什么没有解决方法

更新有关可能的解决方法:

这将是更好地说:“有使用Lambda没有解决方法”,因为一般的解决方法是存在的,尽管他们需要你放弃便捷的lambda语法。 例如,您可以:

  1. 编写明确地捕捉局部类型this与它要求任何其他当地人(由下面的Björn博动的评论启发)一起。
  2. 写一个private方法,而不是一个lambda并传递作为回调(例如,使用std::bind为方便起见)。 如果你想捕捉当地人除了this ,你可以使用更多std::bind在调用点这样做。


Answer 3:

解决方法:

typedef  bool (A::*MemFn)(void) const;

bool A::hasGrandChild() const {
    MemFn f = &A::hasChild;
    return any_of(childs_.begin(), childs_.end(), [=](A const &a) {
            return (a.*f)();
    });
}


Answer 4:

您可以捕获this明确,并使其成为“成员拉姆达”有权访问私有成员。

例如,请考虑下面的示例:

#include <iostream>
class A {
private:
    void f() { std::cout << "Private"; }
public:
    void g() { 
        [this] { 
            f(); 
            // doesn't need qualification 
        }(); 
    }
};
class B {
private:
    void f() { std::cout << "Private"; }
public:
    void g() { [] { f(); }(); } // compiler error
};
int main() {
    A a;
    a.g();
}


Answer 5:

因为拉姆达是不是类的一部分,这是不可能的。 这是一样的制作出来的一流的功能,并调用它,而不是创建一个拉姆达。 当然,它不能访问私有成员。



文章来源: Why is it not possible to use private method in a lambda?
标签: c++ c++11 lambda