【问题标题】:#import still gets "duplicate symbol" error#import 仍然出现“重复符号”错误
【发布时间】:2011-02-14 19:18:13
【问题描述】:

当我编译我的 iPhone 应用程序时,xCode 为 MyConstants.h 中的变量给出“重复符号”错误

我想如果我用过:

#import "MyConstants.h"

这样会避免吗?

但我仍然有问题。

添加信息:

  • 在“链接”期间发生错误。 (我只是使用 xCode 的“Build and Go”按钮。)

  • 我也尝试了(#import 不必要的)#ifndef/def 方法。

    也许我应该问这个:

    如果您需要访问 ALL 源代码文件的 EVERY 部分中的常量...您会在 .h 文件中放入什么?您将使用什么来将该常量包含在代码的其他部分中。

    我认为(但我想不是)它很简单:

  • MyConstants.h> int thisIsGlobal = 123;

    (没有我在任何代码的任何地方重新定义 thisIsGlobal。)

    然后在我的其他每个源文件的顶部添加“#import MyConstants.h”。

  • 【问题讨论】:

    • 这个常量是如何定义的?
    • 错误发生在编译时还是链接时?可能有不同的定义(在不同的标题中)命名相同的符号。比如,标题 A 中的 extern int foo; 和标题 B 中的 NSString* foo();

    标签: iphone c xcode import compiler-errors


    【解决方案1】:

    我这样使用,并且可以工作:(在@interface 之外的 .h 中)

    static NSString * const mkLocaleIdentifierUS = @"en_US";
    static NSString * const mkLocaleUserSystemSettings = nil;
    

    【讨论】:

      【解决方案2】:

      我通常将我的应用程序常量文件放在 Xcode 项目的 MyApplication_Prefix.pch 文件中,通常位于 Other Sources 组中。此pch 文件中包含的任何头文件都将包含在您项目中的所有文件中。

      添加此包含语句后,您将不再需要从项目中的每个文件中包含您的 MyConstants.h 文件 - 它将被自动包含。

      【讨论】:

        【解决方案3】:

        这是因为有问题的符号名称 (thisIsGlobal) 被发送到创建的每个目标文件中,其中包含 thisIsGlobal 声明的标头被包含并且可见。

        另一张海报提供的示例:'extern const int MyConstant;'是最好的方法,除非您需要使值可见,在这种情况下您可以使用枚举:

        int thisIsGlobal = 123; // 不好

        枚举 { thisIsGlobal = 123 }; // 好的

        在大型程序中使用静态会发出很多隐藏符号——不要使用它。使用定义也很可怕(考虑到有更安全的替代方案可用,为什么不使用它们?)。

        【讨论】:

        • > 'extern const int MyConstant;'是最好的方法,除非您需要使值可见 为什么会有人希望全局变量可见?
        • @Fran 定义它的原因有很多,因此它对客户或翻译不可见。私有实现和编译时间是最常见的原因。一个 int 不会严重影响编译时间,但它会影响更复杂类型(即更大的 C++ 对象)的编译时间,或者如果(可见)定义在大型接口/包中的早期 - 那么更改值将需要所有客户端重新编译所有依赖项,包括声明 - 对于大型项目至关重要。同样,私下定义也有很多充分的理由。
        【解决方案4】:

        你可以做的是把你的标题(MyConstants.h):

        extern const int MyConstant;
        extern NSString * const MyStringConstant;
        

        在源文件中,包含上面的标题,但定义常量(MyConstants.m):

        const int MyConstant = 123;
        NSString * const MyStringConstant = @"SomeString";
        

        然后,您只需在使用这些常量的任何其他源文件中包含标头即可。标头只是声明这些常量存在于某处,因此编译器不会抱怨,因为解析这些常量名称是链接器的工作。包含常量定义的源文件被编译,链接器看到这是常量所在的位置,并解析在其他源文件中找到的所有引用。

        在标头中声明和定义常量(未声明为static)的问题在于编译器将其视为包含该标头的每个文件的独立全局变量。当链接器尝试将所有已编译的源链接在一起时,它会遇到与您包含 MyConstants.h 一样多次的全局名称。

        【讨论】:

        • 我使用了您的示例,但链接器给出了此错误:未定义符号:“_abc”,引用自:FirstView.o ld 中的 _abc$non_lazy_ptr:未找到符号 collect2:ld 返回 1 退出状态
        • @Kimberly:您确定包含常量定义的文件(即MyConstants.m)正在编译和链接吗?
        • 我完全不知道文件是否正在编译和链接。我该怎么说?我只是在 xcode 中点击 BUILD AND GO。总是编译得很好......但是当我尝试我的 MyConstants.h 时从来没有。
        • @Kimberly:查看构建结果(即转到构建菜单并单击构建结果,并确保将其设置为显示所有消息(而不是仅问题,默认设置)。确定 MyConstants.m 正在构建,右键单击它(或 Ctrl+单击一键鼠标),然后单击“获取信息”。然后,在顶部,单击“目标”,然后确保目标您正在处理的内容已被选中。
        • 谢谢!但请记住,由于应用此修复仅涉及 .h 文件,因此不会自动重新编译相应的类。我最终删除了派生数据以使其正常工作。不过,清洁应该就足够了。
        【解决方案5】:

        两种选择:

        static const int thisIsGlobal = 123;
        

        #define thisIsGlobal 123
        

        【讨论】:

          猜你喜欢
          • 2015-07-03
          • 1970-01-01
          • 2021-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多