Objective C“static” - 它和C ++一样吗?

时间:2014-03-31 16:27:18

标签: objective-c

我继承了一个看起来非常可疑的代码库,如果我是愚蠢的或者是所有错误的傻瓜,我就无法解决问题。这是要点:

在base.h中

@interface Base
{}
+(id)instance
@end

在base.m

+(id)instance
{
    static dispatch_once_t pred = 0;
    __strong static id me = nil;
    dispatch_once( &pred, ^{ me = [[self alloc] init] });
    return me;
}

在derived1.h

@interface Derived1 : Base {}

在derived2.h中

@interface Derived2 : Base {}

问题似乎是单例生成如下:

[[Derived2 instance] foo];

这肯定会设置" me"永远属于Derived2类型,所以如果我调用

会发生什么
[[Derived1 instance] bar];

这是竞争条件吗?或者static在这里意味着什么略有不同?

3 个答案:

答案 0 :(得分:3)

这不是竞争条件"在该术语的标准使用中,但您是正确的,因为首先调用[Base instance][Derived1 instance][Derived2 instance]中的任何一个确定存储在唯一{{1}中的对象的类型变量。

me的含义与C(++)中的含义完全相同。

解决方案是将static中的声明更改为:

Base

并包含定义三次,每次一次:

+ (instancetype) instance;

这样,三个类中的每一个都有自己的方法和自己的静态变量+ (instancetype)instance { static dispatch_once_t pred = 0; __strong static id me = nil; dispatch_once( &pred, ^{ me = [[self alloc] init]; }); return me; } me的使用,它告诉编译器instancetype返回一个与它被调用的相同类型的对象(这是instance族方法的默认值),改善了编译时类型检查。

HTH

答案 1 :(得分:1)

static是一个C关键字。

作为两者,Objective-C和C ++或多或少只是C编程语言的插件,static在所有三种语言中都是相同的。

是的,它在您的代码示例中是一种竞争条件。 这意味着您的代码将很好地编译,但如果Derived2没有实现方法栏(但Derived1会 - 为了编译器的缘故),那么您将在运行时遇到异常。

答案 2 :(得分:1)

是的,在这种情况下,static变量在C和C ++中的行为相同(并且通过扩展名Obj-C和Obj-C ++)并且您的关注是正确的。

假设+instance类方法未被覆盖,+[Derived1 instance]+[Derived2 instance]将始终返回相同的实例,并且该实例的类型由所调用的确定第一

要使用此模式为每个子类提供单独的单例,每个子类必须覆盖+instance并提供自己的实现。

注意:

  • Derived1.h和Derived2.h的内容在这里无关紧要。检查.m文件以查看是否已覆盖+instance