Ste*_*eve 7 c macros objective-c
我相信我会得到20个人说"你为什么要这样做呢"......但是,我会问我的问题,因为它有点学术性质.
我想用C宏重新定义[ClassName new]为:new(ClassName),我想知道如何做到这一点.我开始时对C宏不太满意(我知道 - 令人尴尬 - 我应该这样) - 而且我绝对不喜欢将它们与我的Objective-C代码混合使用.那么,关于这个问题......
首先,作为预处理器,我可以做一个简单的替换:
#define new(x) [x new]
Run Code Online (Sandbox Code Playgroud)
或者,无论出于何种原因,我是否需要下载到objective-c运行时,并执行更类似于以下的操作:
#define new(x) objc_msgSend(class_createInstance(x, 0), sel_registerName("init"))
Run Code Online (Sandbox Code Playgroud)
做这样的事情有什么不足之处?
这种事情经常被其他人使用,或者,有人会看着它说"你在那里做什么"?(我应该关心)
谢谢
编辑:
事实上,在我发布之后发生了这件事,事实上我之前看到过这种事情 - 在Three20 lib中,他们做了这样的事情:
#define TT_RELEASE_SAFELY(__POINTER) { [__POINTER release]; __POINTER = nil; }
#define TT_INVALIDATE_TIMER(__TIMER) { [__TIMER invalidate]; __TIMER = nil; }
// Release a CoreFoundation object safely.
#define TT_RELEASE_CF_SAFELY(__REF) { if (nil != (__REF)) { CFRelease(__REF); __REF = nil; } }
Run Code Online (Sandbox Code Playgroud)
所以我的问题可能很简单; 这样做有什么不足之处,这是一种相对公认的做法,还是会让我陷入更多困境的事情呢?
首先处理宏,它们对纯文本源代码进行操作。所以,是的,new如果您愿意,您可以让宏生成 Objective-C 语法或纯 C 语法,甚至无效语法。
一般来说,使用宏的缺点是,因为它是在单独的步骤中解析和处理的,所以即使一切看起来都很好,编写的宏也可能不会按照您的预期运行。
例如这个宏:
#define MAX(x,y) x > y ? x : y
Run Code Online (Sandbox Code Playgroud)
看起来不错,但假设你这样使用它:
z = MAX(a,MAX(b,c));
Run Code Online (Sandbox Code Playgroud)
预处理器会将其扩展为如下所示:
z = a > b > c ? b : c ? a : b > c ? b : c;
Run Code Online (Sandbox Code Playgroud)
这实际上不会给你三个参数中的最大值。为了解决这个问题,您需要在宏定义中随意添加括号,即使您认为不需要:
#define MAX(x,y) ((x) > (y) ? (x) : (y));
Run Code Online (Sandbox Code Playgroud)
这解决了这个问题,除了我在末尾添加了一个分号,这是编写大量 C 代码的一个可以理解的习惯,除了现在我们的宏扩展为:
z = ((a) > (((b) > (c) ? (b) : (c));) ? (a) : (((b) > (c) ? (b) : (c));));;
Run Code Online (Sandbox Code Playgroud)
语法错误!
如果你看看MAXObjective-C 中的实际定义方式,你会发现它非常混乱,但这就是你安全编写宏所必须要做的。而且您还需要考虑:
z = MAX(expensiveComputation(), reallyExpensiveComputation())
Run Code Online (Sandbox Code Playgroud)
与函数不同,实际上会执行其中一个函数两次,除非您在宏中使用技巧来基本上模拟参数传递。
所以,回答你的问题,是的,这是完全可能的,但是编写安全的宏确实很难。你这样做是为了可以假装你的 Objective-C 代码实际上是另一种语言的代码......无论如何,你为什么要这样做呢?