【问题标题】:Stateless Lambda and Private members无状态 Lambda 和私有成员
【发布时间】:2019-06-26 02:03:00
【问题描述】:

在某些情况下,当使用 C 语言编写的涉及回调的库进行编程时,我喜欢使用 Lambda 表达式;但是,如果我需要更改类成员变量的状态,我不能将this 直接传递给无状态(函数指针)lambda。但是我可以将this 分配给上下文结构中的数据。我觉得奇怪的是能够访问该成员变量,即使它在类中是私有的。 这是我为演示而编写的示例代码。

#include <iostream>
using std::cout;
typedef struct extradatatype{
    void* data;
}extradata;
extradata e = {0};
typedef void(*callback)(extradata* e);
void cb(callback c){
    c(&e);
}

class Test{
private:
    int x;
public:
    Test(int x){
        this->x = x;
    }
    void setcb(){
        cb([](extradata* e){
            Test* self = reinterpret_cast<Test*>(e->data);
            self->x = 20;
        });
    }

    int getx(){
        return x;
    }
};

int main(){
    Test t(10);
    e.data = &t;
    t.setcb();
    cout << t.getx();

    return 0;
}

在 Lambda 表达式中,Test* self 被分配给 e-&gt;data,但我可以访问 self-&gt;x,就好像它是公共成员而不是私有成员一样。所以我感到困惑的是,lambda 表达式表达式是在 setcb 函数的堆栈/上下文中执行,还是在其他地方作为自己的函数执行,但是 C++ 正在做一些奇怪的技巧来允许私有成员成为访问。因为我假设无状态 lambda 实际上与无法访问类的私有成员的非成员静态函数没有什么不同。

【问题讨论】:

  • setcb 中的 lambda 与 setcb 本身具有相同的访问权限,并且可以执行 setcb 可以执行的任何操作。否则,Lambdas 会很烦人。 lambda 在哪里执行并不重要——访问检查是在编译时执行的,而不是在运行时执行的。
  • 你为什么认为 lambda 就像一个 non-member 静态函数,具体来说?为什么不能像成员静态函数一样(有点接近现实)?静态成员函数将满足这两个属性 - 可以访问私有成员,并且可以作为 C 风格的回调传递。
  • @IgorTandetnik 实际上是的。这确实有道理。它更像是成员静态函数而不是非成员静态函数。我认为由于它是一个 lambda,我以某种方式相信它是在类 Test 之外的上下文中执行的,因为我不能隐式使用 this

标签: c++11 lambda private-members


【解决方案1】:

由于您的 lambda 函数是在类 Test 上下文中定义的,因此它将可以访问类 Test 私有成员(无论它是 this.x 还是 self.x,其中 self 的类型为 Test) .和这个例子类似:

class Example {
private:
    int x;
public:
    int f(Example e) {
        return e.x;
    }
};

其中,由于fExample 的成员,它可以访问e.x,因为e 的类型为Example

如果您将 lambda 函数定义移出类上下文,您将看到预期的错误消息:

void outside(extradata* e);

class Test{
private:
    int x;
public:
    void setcb(){
        cb(outside);
    }
};

void outside(extradata* e) {
    Test* self = reinterpret_cast<Test*>(e->data);
    self->x = 20;  // error here!
}
test.cpp:32:11: error: 'int Test::x' is private within this context
     self->x = 20;
           ^

【讨论】:

  • 哦,好吧,即使你传递了另一个类对象的指针而不是它本身,它仍然可以访问私有成员,因为它是在类本身的上下文中执行的;所以它实际上是一个静态成员函数,不能使用this,但它可以访问私有成员
  • 有点像,是的。但是,如果您捕获它,它将能够使用 this[this](....){....} - 这样this 将在您的 lambda 中可用。
  • 当使用 lambda 代替函数指针时,您无法在上下文中捕获 this
猜你喜欢
  • 2011-12-12
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 2020-03-22
  • 2016-09-10
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多