【问题标题】:What is this double underscore in CocoaCocoa 中的双下划线是什么
【发布时间】:2010-10-08 16:07:17
【问题描述】:

Objective-C 中的单下划线显然是为 Apple 的“内部”使用而保留的(并且在 Apple 声明之前可用于私有实例变量)。但是为什么他们会在他们的 iPhone 的 SQLiteBooks 示例中使用 double-下划线呢?请参阅取自 MasterViewController.m 的这个 sn-p:

+ (EditingViewController *)editingViewController {
    // Instantiate the editing view controller if necessary.
    if (__editingViewController == nil) {
        __editingViewController = [[EditingViewController alloc] initWithNibName:@"EditingView" bundle:nil];
    }
    return __editingViewController;
}

forum 上提到了双下划线的使用,因为它与 C 相关——它是为了“编译器的内部使用”。我想我看不出这在这种情况下如何适用。

我的应用程序中需要一个 ViewController,其行为与 SQLiteBooks 示例项目中的 ViewController 非常相似,但这个双下划线让我感到困惑。

【问题讨论】:

    标签: objective-c cocoa double-underscore


    【解决方案1】:

    无论是 C 编译器还是 Objective-C 编译器,对带有前导下划线的变量名的处理都与任何其他变量名不同。单下划线或双前导下划线只是一个约定,并有效地形成了一个命名空间,很像NSString等Cocoa类中使用的NS前缀。

    查看 SQLiteBooks 代码,MasterViewController.m 定义了这个静态全局变量:

    // Manage the editing view controller from this class so it can be easily accessed from both the detail and add controllers.
    static EditingViewController *__editingViewController = nil;
    

    所以我的猜测是 SQLiteBooks 的作者使用双前导下划线来表示全局变量。

    C 编译器(以及扩展的 Objective-C)保留以两个下划线和一个大写字母开头的名称供编译器供应商使用,为它们提供一个保留的命名空间,用于用于实现标准库的全局变量和函数,或引入新的非标准关键字,如@9​​87654325@。

    虽然 SQLiteBooks 代码在技术上是有效的,但在我看来,它很容易与保留的命名空间混淆。如果您确实重用了该代码,我建议重命名该变量(Xcode 有一个非常好的重命名重构,它会自动为您完成)。

    【讨论】:

    • 我不能说它是否也适用于 C,但在 C++ 中,双下划线用于实现,单下划线后跟大写字母。这意味着 __editingViewController 确实会使用技术上为编译器供应商保留的名称。
    • -1。 __ 或 _A(到 _Z)保留供编译器使用,并调用未定义的行为。如果你给它一个双下划线,预处理器可以做它喜欢的任何事情。它在大多数情况下都有效的事实并不能使它成为有效的 C。
    【解决方案2】:

    对于编译器,下划线被视为任何字母字符。更一般地说,语言扩展或大型库通常使用下划线来避免与用户代码发生冲突。

    使用下划线是有问题的,因为很多组都试图用特定的下划线组合来保留每个名称。

    Apple 传统上使用单个下划线前缀来表示私有实例变量(面向对象语言中的常见样式)。这被认为是暗示每个人都应该在他们的 ivars 前加上下划线,直到 Apple 指出如果 Apple 决定更改其标头而在您的代码中使用下划线可能会与 Cocoa 发生冲突,也许您不应该这样做。所以下划线前缀已经成为一种“不建议”的编码习惯。

    在 C 和 C 派生语言中,任何前后带有双下划线的单词都是非标准语言扩展。查看 Apple 的扩展,例如 __attribute__

    尾随下划线通常作为原始名称的编译器或调试器名称错位版本添加(尤其是当编译器是多通道时),并且通常会避免使用,以便这些名称与原始名称保持明显不同。 Google 在其 Objective-C 本地实例变量后缀下划线,以避免与 Apple 的下划线冲突。

    我的建议:不要使用下划线。您不应该使用与实例变量同名的局部变量(这只是令人困惑)。唯一潜在的冲突是在 setter 方法中的参数和相应的实例变量之间——你应该在参数前面加上一个小写的“a”、“new”(或类似的),因为这清楚地指出参数是传入的值但还不是“the”值。

    【讨论】:

    • -1 根据 C99,双下划线保留供“实现”使用,即预处理器/编译器/库并调用未定义的行为,除非另有说明。它们并不意味着“非标准扩展”,例如__FILE__、__LINE__、__func__。更多详情请见open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
    【解决方案3】:

    这只是一个变量命名约定。它不任何事情。这是程序编写者提醒自己的一种方式,“这是一个私有变量。”

    【讨论】:

    • 所以你是说它已经取代了单个下划线,因为 Apple 声称它是供内部使用的?
    • 是的,和苹果的单下划线是一样的想法。 (不,安德鲁,我不认为我错过了重点。他问他们为什么使用双下划线,我解释了。)
    • -1 双下划线保留供“实现”使用,即预处理器/编译器/库,并根据 C 标准调用未定义的行为。
    【解决方案4】:

    编译器/库供应商将某些前/后缀表示为“保留”的情况并不少见。这主要是为了避免类型/定义/继承变量之间的任何无意冲突。

    您所指的帖子是关于定义的,而不是变量。许多编译器对其提供和依赖的定义使用双下划线。

    至于示例代码为何使用这种风格 - 原作者使用了他在日常工作中可能采用的相同编码风格,并且从未突出显示潜在的冲突。

    您应该按原样保留代码示例,但如果它让您不舒服,那么您可以重命名变量。

    【讨论】:

    • 我也会将该方法重命名为 +(EditingViewController *)sharedEditingViewController { ... ,这是单例的非官方代码约定。
    猜你喜欢
    • 1970-01-01
    • 2018-12-22
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 2013-10-13
    • 2011-11-16
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多