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
命令。 Bool
和 macroArray
都是静态的,但请注意它们没有声明为 static
或 extern
。
这可能不是最佳做法,但我就是这样做的。
【讨论】:
【参考方案4】:Objective-C 中的static
与 C++ 类中的static
的含义不同,在静态类数据成员和静态类方法的上下文中。在 C 和 Objective-C 中,全局范围内的 static
变量或函数意味着该符号具有内部链接。
内部链接意味着该符号是当前翻译单元的本地符号,即当前正在编译的源文件(.c
或.m
)以及它递归生成的所有头文件包括。该符号不能被其他翻译单元引用,并且您可以在其他同名翻译单元中使用具有内部链接的其他符号。
因此,如果您有一个将变量声明为 static
的头文件,则包含该头文件的每个源文件都会获得一个 单独的全局变量——一个源文件中对该变量的所有引用都将引用指向同一个变量,但不同源文件中的引用将引用不同的变量。
如果你想拥有一个全局变量,你不能像在 C++ 中那样在类范围内拥有它。一种选择是使用外部链接创建一个全局变量:在头文件中使用extern
关键字声明变量,然后在一个源文件中定义它没有extern
关键字的全局范围。内部链接和外部链接是互斥的——不能将变量同时声明为extern
和static
。
作为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::