2

根据维基百科,消息传递和调用方法之间的区别是“在消息传递中,每个参数都必须有足够的可用额外内存来将现有参数复制到新消息的一部分中”,而在方法中只调用地址的参数被传递。

消息传递与调用常规方法有何不同,其所有参数都是结构或值类型,即它们都必须完全推入堆栈以便被调用者能够使用它们?

4

3 回答 3

10

一旦进行了实际的函数调用,就没有区别了。消息传递和调用方法的区别在于链接。对于像 c 和 c++ 这样的语言,函数调用在编译时与链接器链接(除了需要一些运行时支持的虚函数)。对于使用诸如objective-c 和smalltalk 之类的消息传递系统的语言,您无法保证在运行之前会运行哪些函数。运行时确定对象是否实际实现了消息中表示的功能。如果它没有实现它,该类通常要么将消息转发到另一个对象,要么抛出异常。但是,如果该类确实实现了它,则运行时会确定实际函数的地址,

总的来说,消息与直接调用方法是一样的,只是运行时会找到要调用的确切函数,而不是在编译时链接它。

于 2011-03-27T20:51:31.560 回答
7

Objective-C 调用 ABI 通常是(如果您愿意,可以编写自己的 ABI)100% 纯 C ABI;参数和返回值的处理方式与普通 C 调用站点完全一样。

一个关键的区别是,Objective-C 调用站点总是编译为 的变体,objc_msgSend()前两个参数总是目标对象 ( self) 和要调用的选择器 ( _cmd)。这就是启用动态调度的原因——在运行时覆盖方法等的能力——这使得 Objective-C 与 C++(或类似的)有很大不同。

对于您可能需要了解的更多信息objc_msgSend()(在运行时和编译器团队之外),我编写了一个由 4 部分组成的系列,提供objc_msgSend().

于 2011-03-27T20:51:50.560 回答
3

您链接到的页面正在讨论远程消息传递,例如 SOAP 或 CORBA。这确实与 Objective-C 消息传递没有太多关系(如果有的话)。(是的,维基百科的 Objective-C 文章链接到它——那个链接真的不应该在那里。)

发送消息和调用方法的区别在于前者是高度动态的。消息名称到处理它的函数的映射在运行时完成,而方法调用在编译时绑定到函数。

这允许一种在 C++ 中无法轻易完成的动态编程。例如,Objective-C 运行时将查找 -forwardInvocation:,如果对象不直接响应指定消息,则调用它。这允许像 NSProxy 这样的类,它可以充当任何其他类的“替身”,而不必知道它是代理的类的所有细节。

另一个例子是在运行时扩展类定义,而不需要重新编译甚至重新启动应用程序——只需在运行时注册实现函数即可。

还有一个例子是支持语言桥梁。例如,我自己的 Cocoa/Perl 桥接器只有一个实现函数来处理发送到 Perl 对象的任何消息 - 它检查消息名称并即时计算应调用的 Perl 函数作为响应。

编辑:顺便说一句,一旦处理给定消息的函数得到解决,调用该函数的机制 - 即构建堆栈框架以传递参数 - 与完成名称到函数绑定时完全相同在编译时。参数以不同方式传递的概念只是偏离主题的维基百科文章引入的红鲱鱼。

于 2011-03-27T20:49:17.787 回答