在某些情况下,当使用用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实际上与无法访问类的私有成员的非成员静态函数没有什么不同。
答案 0 :(得分:1)
由于您的lambda函数是在类Test
的上下文中定义的,因此可以访问类Test
的私有成员(无论是this.x
还是self.x
,其中{{ 1}}的类型为self
)。类似于以下示例:
Test
其中,由于class Example {
private:
int x;
public:
int f(Example e) {
return e.x;
}
};
是f
的成员,因为Example
的类型为e.x
,所以它可以访问e
。
如果将lambda函数定义移出类上下文,则会看到预期的错误消息:
Example
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!
}