【问题标题】:ld: duplicate symbol - caused by constld:重复符号 - 由 const 引起
【发布时间】:2012-03-23 22:02:00
【问题描述】:

我正在定义一个 NSString 以用作 NSError 中的错误域,并且正在复制 ASIHttpRequest 的操作方式。

NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";

我将 const 放在它自己的 .h 文件中 // FPServerAPICoordinatorConstants.h

#ifndef FirePlayer_FPServerAPICoordinatorConstants_h
#define FirePlayer_FPServerAPICoordinatorConstants_h

NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";

#endif

但是当我将它包含在多个 .m 中时

SomeFile.m

#import "FPServerAPICoordinatorConstants.h"

SomeOtherFile.m

#import "FPServerAPICoordinatorConstants.h"

我收到链接器错误“重复符号”

ld: duplicate symbol _FPServerAPIErrorDomain in SomeFile.o and ....SomeOtherFile.o for architecture armv7

所以我将 const 更改为 #define 并且它工作正常。

//  FPServerAPICoordinatorConstants.h

#ifndef FirePlayer_FPServerAPICoordinatorConstants_h
#define FirePlayer_FPServerAPICoordinatorConstants_h


//THIS WAS TRIGGERING link errors
//NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";
//working OK
#define FPServerAPIErrorDomain @"FPServerAPIErrorDomain"

#endif

但是有没有办法让全局空间中的 const 不抛出“重复符号”?

【问题讨论】:

  • 如果您省略包含文件魔术,您的问题是否与以下相同:“我可以在同一源/二进制文件中执行两次 const int i=42; 吗?
  • 是的,但还有“你如何不使用#defines 并在全局空间中使用 const”?可能吗?是首选吗? #define 有效,但为什么有 consts 呢?我是一个 java 人搬进了 Obj-c 我还没有获得 voodoo 101 的资格
  • 你根本没有复制 ASIHttpRequest 正在做的事情。回去再看一遍。

标签: objective-c c constants linker-errors c-preprocessor


【解决方案1】:

在你想要的头文件中:

extern NSString *const FPServerAPIErrorDomain;

然后在一个实现文件中(所以可能你想要一个FPServerAPICoordinatorConstants.m)你会想要:

NSString *const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain";

然后您可以将标头导入多个文件,而不会出现重复符号错误。

[顺便说一句,如果您使用的是#import,则不需要#ifndef 守卫。]

【讨论】:

  • 哈!当我从模板添加头文件时,苹果将 ifndef 放入:)
  • 这可能是因为您是从“C 标头”模板添加的。如果您使用 C 风格 #includes,那么默认情况下会包含它们。但是您使用的是 Objective-C 风格的#imports。所以摆脱守卫。
  • 非常感谢您的回答。为我节省时间。
【解决方案2】:

不可能在同一个命名空间中两次实例化同一个(全局)变量(不会出错)。

【讨论】:

  • 使用 //NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain" 有什么好处吗?在#define FPServerAPIErrorDomain @"FPServerAPIErrorDomain"
【解决方案3】:

每个符号只能定义一次;也就是说,它应该只定义在一个 m 文件中。通过将定义放在头文件中,它会在包含该头文件的每个 m 文件中进行定义。

在您的一个 m 文件中定义它(以最相关的为准),并将您在标题中的内容更改为声明(使用 extern 关键字)。

定义为数据腾出空间;该声明只是告诉编译器在其他地方有一个定义。所以每个使用该常量的m文件都需要有一个声明,但只有一个m文件应该有定义。

【讨论】:

  • 使用 //NSString* const FPServerAPIErrorDomain = @"FPServerAPIErrorDomain" 有什么好处吗?在#define FPServerAPIErrorDomain @"FPServerAPIErrorDomain"
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多