Objective-C 静态、外部、公共变量

Posted

技术标签:

【中文标题】Objective-C 静态、外部、公共变量【英文标题】:Objective-C static, extern, public variables 【发布时间】:2011-11-30 08:02:38 【问题描述】:

我希望有一个变量,我可以通过导入头文件在任何地方访问它,但我也希望它是静态的,因为只创建了一个。在我的 .m 文件中,我指定了

static BOOL LogStuff = NO;

在初始化方法中我设置了日志记录值:

+ (void)initialize

    LogStuff = ... //whatever

但是我希望能够通过导入 .h 文件在任何地方访问我的变量,所以我想做这样的事情:

static extern BOOL LogStuff;

但我不允许这样做。有可能做我想做的事情吗?谢谢

【问题讨论】:

【参考方案1】:

如果LogStuff是一个静态类字段,也许你可以实现静态getter和setter?

+ (void)setLogStuff:(BOOL)aLogStuff;
+ (BOOL)logStuff;

【讨论】:

【参考方案2】:

在你的头文件中声明它extern BOOL#import 您的标头不知道或不关心外部符号是否为静态的文件。

【讨论】:

【参考方案3】:

我通常将这种布局用于我的静态:

NSMutableArray *macroArray;
BOOL keepMacro;

+ (void) startMacro

    if (macroArray == nil)
    
        macroArray = [[NSMutableArray alloc] initWithCapacity:100];
    

    [macroArray removeAllObjects];
    keepMacro = YES;

这是我的应用程序中的startMacro 命令。 BoolmacroArray 都是静态的,但请注意它们没有声明为 staticextern

这可能不是最佳做法,但我就是这样做的。

【讨论】:

【参考方案4】:

Objective-C 中的static 与 C++ 类中的static 的含义不同,在静态类数据成员和静态类方法的上下文中。在 C 和 Objective-C 中,全局范围内的 static 变量或函数意味着该符号具有内部链接

内部链接意味着该符号是当前翻译单元的本地符号,即当前正在编译的源文件(.c.m)以及它递归生成的所有头文件包括。该符号不能被其他翻译单元引用,并且您可以在其他同名翻译单元中使用具有内部链接的其他符号。

因此,如果您有一个将变量声明为 static 的头文件,则包含该头文件的每个源文件都会获得一个 单独的全局变量——一个源文件中对该变量的所有引用都将引用指向同一个变量,但不同源文件中的引用将引用不同的变量。

如果你想拥有一个全局变量,你不能像在 C++ 中那样在类范围内拥有它。一种选择是使用外部链接创建一个全局变量:在头文件中使用extern关键字声明变量,然后在一个源文件中定义它没有extern 关键字的全局范围。内部链接和外部链接是互斥的——不能将变量同时声明为externstatic

作为Panos suggested 的替代方法是使用类方法而不是变量。这将功能保持在类的范围内,这在语义上更有意义,如果您愿意,也可以将其设为 @private。它确实增加了边际性能损失,但这不太可能成为您的应用程序的瓶颈(如果您怀疑是,请始终先配置文件)。

【讨论】:

"然后在一个源文件中,在全局范围内定义它而不使用 extern 关键字" => 如果我不这样做会怎样?我很惊讶没有编译器错误。 @huggie:您很可能会收到链接器错误,例如“未找到符号”或“重复符号”。 +1 表示“内部链接和外部链接互斥” "在一个源文件中对该变量的所有引用都将引用同一个变量,但不同源文件中的引用将引用不同的变量。"我创建了一个项目来尝试重新创建它,但我遇到了麻烦。我创建了一个声明静态变量的标头 (StaticHeader01.h),以及导入 StaticHeader01.h 并打印出静态变量的内存地址的另外两个文件 (Test01.h|m Test02.h|m)。但是,内存地址是相同的。你能指出我错过了什么吗? @AdamRosenfield: 声明一个全局的 const NSString 有和没有 static 关键字有什么区别吗?如果它是全局的,关键字 static 是否添加任何值?静态 NSString *const kSiteURL = @“google.com”; vs NSString *const kSiteURL = @“google.com”;【参考方案5】:

单独的全局变量(每个源文件一个):

// .h
static NSString * aStatic;

//.m
static NSString * aStatic = @"separate";

唯一的全局变量:

// .h
extern NSString * anExtern;

// .m
NSString * anExtern = @"global";

【讨论】:

以上是关于Objective-C 静态、外部、公共变量的主要内容,如果未能解决你的问题,请参考以下文章

GameEngine.obj : error LNK2001: 无法解析的外部符号 private: static class GameEngine * GameEngine::

MFC C++ 使用静态成员和编译问题

Objective-C 中的静态变量——它们有啥作用?

详解Objective-C中静态变量使用方法

在 Objective-C 类别中初始化一个静态变量

帮助在monotouch中绑定一个静态objective-c库