类似/跟进此问题:在Objective-C 中定义接受块并返回块的块的语法
我知道这不是我想做的事情,但我想明白为什么我不能用一个typedef来定义:
typedef void (^XYZSimpleBlock)(void);
typedef XYZSimpleBlock (^ComplexBlock)(void);
为什么上面的是有效的,而这是无效的?
typedef void(^)(void) (^ComplexBlock)(void);
如果我找到一个类似的答案,我可以试着像编译器一样解析它,但我是一个糟糕的编译器。
按照C的左-右规则,第一个标识符不是ComplexBlock
吗?
typedef void(^)(void) (^ComplexBlock)(void);
// parser reads left right and finds ComplexBlock first
然后它会向右移动并找到声明的结束,然后向左移动直到找到插入符号,然后向右移动以解释参数列表。
这就把我们带到
typedef void(^)(void) (^ComplexBlock)(void);
// | unhandled |compiled/interpreted|
在这一点上,它不能将void(^)(void)
读取为返回类型,这是怎么回事?
让我困惑的是,使用typedef基本上只是一个#define
,所以它不应该与上面的基本相同吗?
typedef void (^XYZSimpleBlock)(void);
same as:
void(^)(void)
so:
typedef XYZSimpleBlock (^ComplexBlock)(void);
should be the same as:
typedef void(^)(void) (^ComplexBlock)(void);
我错过了什么。。。
正确的语法是:
typedef void (^(^ComplexBlock)(void))(void);
当您构造这样复杂类型的声明时,从更简单的类型开始并用"表达式"代替标识符会有所帮助。
因此,例如,声明一个不带参数并返回void
:的函数
void a_func(void);
现在,我们想要声明一个函数指针a_func_ptr
,它是指向相同类型函数的指针。我们希望表达式*a_func_ptr
与a_func
的类型相同,所以我们将括号中的表达式放入上面的表达式中,得到:
void (*a_func_ptr)(void);
如果我们想要块指针而不是函数指针,我们使用^
而不是*
:
void (^a_block_ref)(void);
(人们觉得块语法令人沮丧的一个原因是,人们从来没有真正写过表达式^a_block_ref
来"取消引用"块变量,所以实现这种飞跃并不明显。)
采用以上内容并从中生成typedef
(而不是变量声明)就是获得的方法
typedef void (^XYZSimpleBlock)(void);
但是,让我们暂时回到函数指针a_func_ptr
。假设您想要声明一个返回函数指针的函数func_returns_func
。将函数调用表达式放入a_func_ptr
所在的位置。也就是说,将func_returns_func()
放入:
void (*func_returns_func())(void);
现在,在声明函数时,您需要使用void
来表示无参数,因此您可以这样做:
void (*func_returns_func(void))(void);
请注意,您不会收集或隔离标识符左侧的返回类型。它围绕着标识符。
现在,您将*
更改为^
,以获得一个返回块引用而不是函数指针的函数:
void (^func_returns_block(void))(void);
让我们制作一个指针,指向一个返回块引用的函数。将(*ptr_to_func_returns_block)
放入func_returns_block
并获取:
void (^(*ptr_to_func_returns_block)(void))(void);
再次,用^
替换*
以获得对返回块引用的块的引用:
void (^(^block_returns_block)(void))(void);
我们就在这里。只需更改名称,即可获得
void (^(^ComplexBlock)(void))(void);