首页 Objective-C 从 C++ 到 Objective-C(11):实例化(续二)

从 C++ 到 Objective-C(11):实例化(续二)

0 4K

默认构造函数:指定初始化函数

在 Objective-C 中,默认构造函数没有实在的意义,因为所有对象都是动态分配内存,也就是说,构造函数都是确定的。但是,一个常用的构造函数确实可以精简代码。事实上,一个正确的初始化过程通常类似于:

if (!(self = [super init])) // "init" 或其他父类恰当的函数
    return nil;
// 父类初始化成功,继续其他操作……
return self;

剪贴复制代码是一个不良习惯。好的做法是,将共同代码放到一个独立的函数中,通常称为“指定初始化函数”。通常这种指定初始化函数会包含很多参数,因为 Objective-C 不允许参数有默认值。

-(id) initWithX:(int)x
{
    return [self initWithX:x andY:0 andZ:0];
}

-(id) initWithX:(int)x andY:(int)y
{
    return [self initWithX:x andY:y andZ:0];
}

// 指定初始化函数
-(id) initWithX:(int)x andY:(int)y andZ:(int)z
{
    if (!(self = [super init]))
        return nil;
    self->x = x;
    self->y = y;
    self->z = z;
    return self;
}

如果指定初始化函数没有最大数量的参数,那基本上就没什么用处:

// 以下代码就有很多重复部分
-(id) initWithX:(int)x // 指定初始化函数
{
    if (!(self = [super init]))
        return nil;
    self->x = x;
    return self;
}

-(id) initWithX:(int)x andY:(int)y
{
    if (![self initWithX:x])
        return nil;
    self->y = y;
    return self;
}

-(id) initWithX:(int)x andY:(int)y andZ:(int)z
{
    if (![self initWithX:x])
        return nil;
    self->y = y;
    self->z = z;
    return self;
}

初始化列表和实例数据的默认值

Objective-C 中不存在 C++ 构造函数的初始化列表的概念。然而,不同于 C++,Objective-C 的alloc会将所有实例数据初始化成 0,因此指针也会被初始化成nil。C++ 中,对象属性不同于指针,但是在 Objective-C 中,所有对象都被当做指针处理。

虚构造函数

Objective-C 中存在虚构造函数。我们将在后面的章节中详细讲诉这个问题。

类构造函数

在 Objective-C 中,类本身就是对象,因此它也有自己的构造函数,并且也能够被重定义。它显然是一个类函数,继承自NSObject,其原型是+(void) initialize;

第一次使用这个类或其子类的时候,这个函数将被自动调用。但这并不意味着,对于指定的类,这个函数只被调用一次。事实上,如果子类没有定义+(void) initialize;,那么 Objective-C 将调用其父类的+(void) initialize;

析构函数

在 C++ 中,析构函数同构造函数一样,是一个特殊的函数。在 Objective-C 中,析构函数也是一个普通的实例函数,叫做dealloc。C++ 中,当对象被释放时,析构函数将自动调用;Objective-C 也是类似的,但是释放对象的方式有所不同。

析构函数永远不应该被显式调用。在 C++ 中存在这么一种情况:开发者自己在析构时管理内存池。但是在 Objective-C 中没有这种限制。你可以在 Cocoa 中使用自定义的内存区域,但是这并不会影响平常的内存的分配、释放机制。

C++

class Point2D
{
public:
    ~Point2D();
};

Point2D::~Point2D() {}

Objective-C

@interface Point2D : NSObject
-(void) dealloc; // 该方法可以被重定义
@end

@implementation Point2D
// 在这个例子中,重定义并不需要
-(void) dealloc
{
    [super dealloc]; // 不要忘记调用父类代码
}
@end

发表评论

关于我

devbean

devbean

豆子,生于山东,定居南京。毕业于山东大学软件工程专业。软件工程师,主要关注于 Qt、Angular 等界面技术。

主题 Salodad 由 PenciDesign 提供 | 静态文件存储由又拍云存储提供 | 苏ICP备13027999号-2