"void (*)(int)"与"void (^)(int)"相同吗?

Does 'void (*)(int)' the same with 'void (^)(int)'?

本文关键字:int void      更新时间:2023-10-16

今天,我正在处理从C++到Objective-C方法的回调传递
最后,我计算出了它,但有几个代码让我感到困惑。
在Objective-c中,人们通常使用块来实现回调,块声明如下:

returnType(^blockName)(parameterTypes)

我还学习了C++回调,一个定义如下的相同类型的回调:

returnType(*funcName)(parameterTypes)

当我从C++向Objective-C传递回调时,编译器警告我:

"无法用'void(*)(int)'类型的右值初始化'void(^)(int

最后,我将^更改为*,它起作用了。我想知道,^*在定义上有什么区别,它们有相同的行为吗?

这是一个块:

returnType (^blockName)(parameterTypes)

这是一个函数指针:

returnType (*funcName)(parameterTypes)

它们不兼容。

标准C和C++没有可调用的块。然而,显然,这些语言的一些编译器确实将该功能作为扩展来实现。我看到的一些文档表明,这也是苹果对Objective C的扩展,但由于Objective C在苹果世界之外很少使用,这可能是一个没有区别的区别。

在任何语言中,如果你将回调实现为函数,那么你必须通过函数指针将该回调呈现给预期的调用者,调用者必须准备好以这种形式接受它。另一方面,如果你以块的形式实现回调,那么你必须通过块指针将其呈现给调用者,并且调用者必须准备好接受形式的。这两者是不可互换的,而且它们有不同的语法,正如您所展示的那样。不过,可以设计一种机制,通过单独的参数或完全独立的登记职能,接受这两种形式。

Objective-C块(^)与函数指针(*)不兼容
与函数指针相比,它们的优点是能够从周围的上下文中捕获值和变量(它们是闭包)。

编写一个从块调用函数指针的包装器很容易:

typedef int (*funptr)(int);
typedef int (^funblock)(int);

int use_block_callback(int y, funblock fb)
{
    return fb(y);
}
int use_funptr_callback(int y, funptr f)
{
     return use_block_callback(y, ^ int (int x) { return f(x); }); 
}
int add_one(int x) { return x + 1; }
int foo(int x)
{
    return use_funptr_callback(23, add_one);
}
// Or
int (*some_pointer)(int) = add_one;
int (^some_block)(int) = ^ int (int x) { return some_pointer(x); } 

(关于块的"用Objective-C编程"。)

相关文章: