为什么 Objective-c 对象必须动态分配?为什么我必须使它成为一个指向对象的指针,不像在 C++ 中我可以在堆栈上创建它们?谢谢。
3 回答
主要原因:不知道要保留多少堆栈大小。
现有的约定和用途也使解除限制相当困难。
在这种情况下,动态消息传递无关紧要,因为在初始化时设置正确的“vtable”是微不足道的。
在 C++ 中,堆栈对象的大小始终是已知的(如果它是错误的,你知道会发生什么)。objc alloc/init 序列可以返回多种类型中的任何一种——每种类型都有不同的大小(它本质上是一个工厂),或者什么也没有。
大小也可以在运行时变化(例如,您可以通过运行时向类添加字段)。
更新 1
我对此很好奇,所以我做了一个小测试程序作为概念证明。
我能够实现一个简单的基于堆栈的 objc 类层次结构,它还实现了大量NSObject
的接口——当然,省略了引用计数和动态分配接口,因为它与概念证明无关。无论如何,我的简单类层次结构与 NSObject 类或协议不完全兼容,因此出于显而易见的原因,它不应该用于预期 NSObject 类型的地方。因此,如果您真的想要基于堆栈的 objc 对象,则可以(并且不是特别困难)实现这一点。
您不必做任何与 c++ 不同的事情来保留堆栈空间。在某些领域(考虑工厂方法、类集群等),要保留的堆栈大小仍然是一个限制。
还有一些运行时功能在默认情况下不起作用。这里最好的例子是在运行时添加 ivars 的能力。如果需要,您实际上可以容纳此功能。我没有打扰那个练习。
自然地,基本接口可能会有几个偏差——我为了好玩而做出的一个偏差是增加了交换活对象的实现(类型)的能力。
玩得开心
更新 2
事实证明,GCC 接受了我写的概念证明。不幸的是,由于在保留正确大小时可能遇到的问题/危险(考虑到语言的动态特征......),这已在 clang 中被禁止。例如:clang 禁止sizeof(NSObject)
。那好吧。
Objective-c 是一种动态语言,这意味着它的一切都可以在运行时改变。对象的类对象仅在从可执行文件加载时创建,并且可以按类别进行更改。此外,运行时可以实例化属性的变量。由于对象在编译后会发生很多变化,因此在使用之前无法创建它。
这是因为 Objective-C 使用动态或后期绑定的方式。与 C++ 不同,在 C++ 中,您总是可以选择通过对象调用类的函数,还是通过同一类甚至超类的指针调用。在后一种情况下,需要多态性。
然而,在 Objective-C 中总是存在在运行时确定正确函数的能力。不同之处在于,例如在 C++ 中,编译器必须确保使用的函数存在,而在 Objective-C 中,编译器并不真正关心,运行时系统只决定。