【问题标题】:Equivalent of public static final variables公共静态最终变量的等价物
【发布时间】:2013-02-16 18:55:47
【问题描述】:

我知道在头文件中的变量声明之前放置单词extern 声明了全局静态变量的存在而不初始化它。我也明白,如果我导入包含 extern 变量的文件,我可以在没有类/文件名的情况下引用它们。但是在哪里定义它们和它们的价值呢?

我想要做的是创建一个带有全局常量的常量类,我想在整个 iOS 应用程序的代码中使用它。

有人把它们放在这样的界面中吗?

Example.h

#import <Foundation/Foundation.h>
@interface Constraints : NSObject
{

extern   NSString * const PREFS_NAME;

}

或者像这样放在界面之外

Example.h

#import <Foundation/Foundation.h>

extern   NSString * const PREFS_NAME;    

@interface Constraints : NSObject
{

}

那么在实现 .m 文件中如何初始化外部值?

在这样的执行区域内?

Example.m

#import "Constraints.h"

@implementation Constraints

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@end

或者像这样在实现区域之外初始化它们:

Example.m

#import "Constraints.h"

/**PRefecences name for the application**/
const  NSString * PREFS_NAME = @"MyApp_Prefs";

@implementation Constraints

@end

或者我是否在构造函数中为它们提供初始值?或者前面带有+的任意静态样式方法,即+(void) setAppConstraints

我尝试了几种组合,但总是遇到错误,例如“使用不同类型重新定义 'xVariable'”。或者关于“外部没有初始化接口”的东西(或者类似的东西,我忘记了)。所以我想知道如何正确声明和初始化它们以形成与Java中public static final变量相同的角色。

还有extern 命令的限制是什么?我知道我可以externNSIntegerNSString,但是NSArray 呢?

我问这个问题是因为关于在 Objective-C 中使用 extern 的信息似乎有很多误导性或不完整的信息。许多答案似乎是推测性的。我希望这个问题不仅对我来说是一个很好的资源,而且可以限制更多关于extern 基础知识的类似问题。

【问题讨论】:

  • 如果你想“创建一个常量类”,这与全局变量无关,因为它们不属于一个类。为此,您需要 ivars。
  • @Josh Cashwell 可能是一个类似的问题。但正如我在问题文本中所说,我在 S/O 上找到的所有答案都不完整,或者留下的问题多于提供的答案。
  • @Josh Caswell 我想创建一个全局可访问的常量值。这并不向我建议 iVars。我想我可以使用单例,但这仍然不能解释如何使用 extern 来实现这一点,如果我错了,它会纠正我是命令的有效用例,也是它设计的用例。
  • 你的问题有几个误解,所以我很难相信你已经真的阅读了你说你找到的所有重复项。至于“全局可访问的常量值”,如果这是你想要的,那么你就不要一个类。

标签: objective-c syntax extern variable-declaration


【解决方案1】:

您在声明它的文件中定义它的值,在您的情况下是 Example.m;您仍然可以重新分配此变量,因此 Example.h 中的声明如下所示:

extern  NSString * PREFS_NAME;

这样每个导入 Example.h 的文件都可以访问这个变量。 Objective-C 中 public static final 的等价物是 const。如果您还希望它公开,您应该将其设为类实例变量,但在这种情况下您不需要它,因为它已经可以在任何地方访问。所以在这种情况下,它将是:

// .m file
NSString* const PREFS_NAME = @"MyApp_Prefs";
// .h file
extern NSString* const PREFS_NAME;

还要注意 const NSString* 与 NSString* const 不同。后者是一个指向 NSString 的 const 指针。前者没有意义,即使它是正确的语法。在 Objective-C 中, const 限定符不影响对象,而是有可变和不可变类。这在 C++ 中是有意义的,这意味着您可以在实例上只使用 const 方法。

【讨论】:

  • 这个"NSString* const PREFS_NAME = @"MyApp_Prefs";"是在 @ 实现和 @end 配对的内部还是外部?
  • 在外面,因为它不是 ivar。
  • “你可以在实例上只使用 const 方法”是什么意思? NSString 中的方法必须是 const 吗?没看懂
【解决方案2】:

extern 用于通知编译器您将使用在另一个编译单元中定义的变量或函数。

当您说extern const NSString *PREFS_NAME 时,您是在说“将这个编译单元中对 PREFS_NAME 的所有引用替换为变量 PREFS_NAME,因为它在另一个文件中定义。”因此,当您尝试在 .m 中分配 PREFS_NAME 时,您所做的只是尝试分配一个变量,尽管它有名称,但它并不存在。声明变量extern 只是变量或函数的声明,而不是该变量或函数的定义。它让编译器知道 name 正在使用中,并且链接器将负责处理它,但即使您在此处提供类型,它实际上也不会留出空间对于变量,它期望在实际定义变量的编译单元中留出空间。

你一起编译三个或四个不同的源代码文件,其中三个可以声明:

extern int buffer[];

并且可以声明

int buffer[BUFSIZE];

在其全局范围内,链接器的工作是将三个声明的对extern buffer 的引用解析为第四个缓冲区的实际定义。

extern 是 C 变量和函数,就像 @class 是 Objective-C 类一样,它是一个前向声明,向编译器承诺,当你看到一个未定义的名称时,你不必惊慌失措在这里,因为链接器会回答您可能遇到的任何挥之不去的问题。

【讨论】:

  • 这是我目前所理解的。那么如何初始化一个外部变量,让整个项目都能看到它和它的值呢?
  • 您可以在第一次声明变量extern 时在.h 文件中初始化它,或者在.m 文件的全局范围内分配它们。初始化时不会使用extern 关键字,也不会使用static 关键字。 staticextern相反,它将变量的定义限制在编译单元内,不允许其他人引用。
  • PS 大多数在 Obj-C 中做这件事的人只会做#define PREFS_NAME @"MyApp_Prefs" ...我们都在想到public static final 以及它可能意味着什么时尖叫起来:)
  • 我今天没有 Xcode,所以我不能保证,但你在 .h 中的声明应该在你的 @interface 之外并且看起来基本正确。您在 .m 中的行应该在您的实施之外,只需阅读:NSString *PREFS_NAME=@"MyApp_Prefs"; 不需要进一步的资格,还要确保您的 consts 两次都在同一个地方。 const NSString *NSString * const 表示不同的东西。
  • 关于your first comment:你应该在声明时初始化。这是一个编译器警告,有充分的理由:如果您在标头中初始化变量,则在导入标头的任何地方都会收到链接器错误。
猜你喜欢
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
相关资源
最近更新 更多