通过 Lambda 访问私有成员函数
Accessing private member function via Lambda
在一个项目中,我有一个C-API,它使用C风格的函数指针作为回调。在其中一个回调中,我需要访问对象 Foo
的私有函数。请注意,API-调用是在我的 class 的函数中完成的。由于未显示代码,我有一个对象句柄作为我可以访问的 void*
。
除了构造容易出错之外,通过将 lambda 作为回调传递,我能够访问我的对象的私有函数。
这有点出乎意料,但欢迎来到我这里。我还没有发现任何关于这种行为的信息,所以我想请问是否有人可以阐明为什么这是实际有效的。我不知道 lambda 正在捕获某些东西,但它似乎与实际范围界定有关。
我正在使用 C++17 和 gcc 10.2。
这是一个示例代码块:
void TestFunc(void (*)(void*)) {
}
class Foo {
public:
Foo() {
TestFunc([](void* handle){
auto foo = reinterpret_cast<Foo*>(handle);
foo->BarFunc();
});
};
private:
void BarFunc() {};
};
您的代码可以正常工作,因为标准允许这样做。所以首先我们有这个 (C++20 [expr.prim.lambda.closure]p2):
The closure type is declared in the smallest block scope, class scope,
or namespace scope that contains the corresponding lambda-expression.
<...>
在您的示例中,我们有一个块作用域,所以最后我们有一个未命名的本地 class 声明,并且根据 [class.local]p1:
A class can be declared within a function definition; such a class is
called a local class. The name of a local class is local to its
enclosing scope. The local class is in the scope of the enclosing
scope, and has the same access to names outside the function as does
the enclosing function
在一个项目中,我有一个C-API,它使用C风格的函数指针作为回调。在其中一个回调中,我需要访问对象 Foo
的私有函数。请注意,API-调用是在我的 class 的函数中完成的。由于未显示代码,我有一个对象句柄作为我可以访问的 void*
。
除了构造容易出错之外,通过将 lambda 作为回调传递,我能够访问我的对象的私有函数。 这有点出乎意料,但欢迎来到我这里。我还没有发现任何关于这种行为的信息,所以我想请问是否有人可以阐明为什么这是实际有效的。我不知道 lambda 正在捕获某些东西,但它似乎与实际范围界定有关。 我正在使用 C++17 和 gcc 10.2。
这是一个示例代码块:
void TestFunc(void (*)(void*)) {
}
class Foo {
public:
Foo() {
TestFunc([](void* handle){
auto foo = reinterpret_cast<Foo*>(handle);
foo->BarFunc();
});
};
private:
void BarFunc() {};
};
您的代码可以正常工作,因为标准允许这样做。所以首先我们有这个 (C++20 [expr.prim.lambda.closure]p2):
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. <...>
在您的示例中,我们有一个块作用域,所以最后我们有一个未命名的本地 class 声明,并且根据 [class.local]p1:
A class can be declared within a function definition; such a class is called a local class. The name of a local class is local to its enclosing scope. The local class is in the scope of the enclosing scope, and has the same access to names outside the function as does the enclosing function