• 从 C++ 到 ObjectiveC 之实例化


    类的实例化位导致两个问题:构造函数、析构函数和赋值运算符如何实现,以及如何分配内存。

    在 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++

    //Language:  C++
    Foo* foo = new Foo;

    Objective-C

    Language:  Objective-C
    Foo* foo1 = [Foo alloc];
    [foo1 init]; // 这是不好的行为:应该使用 init 的返回值
    Foo* foo2 = [Foo alloc];
    foo2 = [foo2 init]; // 正确,不过看上去很啰嗦
    Foo* foo3 = [[Foo alloc] init]; // 正确,这才是通常的做法


    为检查内存分配是否成功,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

    Language:  Objective-C
    @interface Point2D : NSObject
    {
        int x;
        int y;
    }
     
    // 注意,在 Objective-C 中,id 类似于 void*
    // (id) 就是对象的“一般”类型
    -(id) initWithX:(int)anX andY:(int)anY;
    @end
     
    @implementation Point2D
     
    -(id) initWithX:(int)anX andY:(int)anY
    {
        // 调用父类的初始化方法
        if (!(self = [super init])) // 如果父类是 NSObject,必须进行 init 操作
            return nil; // 如果父类 init 失败,返回 nil
        // 父类调用成功,进行自己的初始化操作
        self->x = anX;
        self->y = anY;
        return self; // 返回指向自己的指针
    }
    @end
     
    ...
    Point2D* p1 = [[Point2D alloc] initWithX:3 andY:4];




    作者:
    出处:http://www.cnblogs.com/ChenYilong/(点击RSS订阅)
    本文版权归作者和博客园共有,欢迎转载,
    但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    Leecode刷题之旅-C语言/python-67二进制求和
    maven 聚合
    maven 继承
    maven 常用命令
    maven 术语
    maven安装
    RabbitMQ 消费消息
    RabbitMQ 生产消息并放入队列
    RabbitMQ 在 web 页面 创建 exchange, queue, routing key
    mybatis 通过实体类进行查询
  • 原文地址:https://www.cnblogs.com/ChenYilong/p/2808620.html
Copyright © 2020-2023  润新知