-1

在某些情况下,当使用 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->data我可以访问self->x它,就像它是公共成员而不是私有成员一样。所以我感到困惑的是,lambda 表达式表达式是在setcb函数的堆栈/上下文中执行,还是在其他地方作为自己的函数执行,但是 C++ 正在做一些奇怪的技巧来允许访问私有成员。因为我假设无状态 lambda 实际上与无法访问类的私有成员的非成员静态函数没有什么不同。

4

1 回答 1

0

由于您的 lambda 函数是在类Test上下文中定义的,因此它将可以访问类Test私有成员(无论它是this.xself.x在哪里self是 type Test)。它类似于此示例:

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

其中,sincef是 的成员Example,它可以访问e.xbecausee有 type 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;
           ^
于 2019-06-26T03:21:45.383 回答