在 C++ 中,变量默认是“自动的”:除非被声明为 static,否则变量仅在自己的定义块中有意义。动态分配的内存可以一直使用,直到调用了 free() 或者 delete。C++ 中,所有对象都遵循这一规则。
然而在 Objective-C 中,所有对象都是动态分配的。其实这也是符合逻辑的,因为 C++ 更加 static,而 Objective-C 则更加动态。除非能够在运行时动态分配内存,否则 Objective-C 实现不了这么多动态的特性。
构造函数和初始化函数
分配 allocation 和初始化 initialization 的区别
在 C++ 中,内存分配和对象初始化都是在构造函数中完成的。在 Objective-C 中,这是两个不同的函数。
内存分配由类方法 alloc 完成,此时将初始化所有的实例数据。实例数据将被初始化为 0,除了一个名为 isa 的 NSObject 的指针。这个指针将在运行时指向对象的实际类型。实例数据根据传入的参数初始化为某一特定的值,这一过程将在一个实例方法 instance method 中完成。这个方法通常命名为 init。因此,构造过程被明确地分为两步:内存分配和初始化。alloc 消息被发送给类,而 init 消息则被发送给由 alloc 创建出来的新的对象。初始化过程不是可选的,alloc 之后应该跟着 init,之后,父类的 init 也会被调用,直到 NSObject 的 init 方法。这一方法完成了很多重要的工作。
在 C++ 中,构造函数的名字是规定好的,必须与类名一致。在 Objective-C 中,初始化方法与普通方法没有什么区别。你可以用任何名字,只不过通常都是选用 init 这个名字。然而,我们还是强烈建议,初始化方法名字一定要用 init 或者 init 开头的字符串。
使用 alloc 和 init
调用 alloc 之后将返回一个新的对象,并且应该给这个对象发送一个 init 消息。init 调用之后也会返回一个对象。通常,这就是初始化完成的对象。有时候,如果使用单例模式,init 可能会返回另外的对象(单例模式要求始终返回同一对象)。因此,init 的返回值不应该被忽略。通常,alloc 和 init 都会在一行上。
C++
Objective-C
为检查内存分配是否成功,C++ 可以判断 new 返回的指针是否是 0(如果使用的是 new(nothrow) 运算符)。在 Objective-C 中,检查返回值是否是 nil 就已经足够了。
初始化方法的正确示例代码
一个正确的初始化方法应该有如下特点:
- 名字以 init 开始;
- 返回能够使用的对象;
- 调用父类的 init 方法,直到 NSObject 的 init 方法被调用;
- 保存 [super init...] 的返回值;
- 处理构造期间出现的任何错误,无论是自己的还是父类的。
下面是一些代码:
C++
//Language: C++
class Point2D
{
public:
Point2D(int x, int y);
private:
int x;
int y;
};
Point2D::Point2D(int anX, int anY) {x = anX; y = anY;}
...
Point2D p1(3,4);
Point2D* p2 = new Point2D(5, 6);
Objective-C