【问题标题】:Why is it that I can include a header file in multiple cpp files that contains const int and not have a compiler error?为什么我可以在多个包含 const int 且没有编译器错误的 cpp 文件中包含一个头文件?
【发布时间】:2012-04-15 16:25:03
【问题描述】:

假设我有文件 a.cpp b.cpp 和文件 c.h。两个 cpp 文件都包含 c.h 文件。头文件包含一堆 const int 定义,当我编译它们时,我没有收到任何错误,但我可以访问这些 const ,就好像它们是全局变量一样。那么问题来了,如果我有多个 const 定义并且这些 const int 具有类似全局的作用域,为什么我不会收到任何编译错误?

【问题讨论】:

    标签: c++ compilation header include


    【解决方案1】:

    这是因为在命名空间范围内的 const 声明意味着内部链接。具有内部链接的对象仅在定义它的翻译单元中可用。所以从某种意义上说,你在c.h 中拥有的一个const 对象实际上是两个不同的对象,一个在a.cpp 内部,一个在b.cpp 内部。

    换句话说,

    const int x = ...;
    

    等价于

    static const int x = ...;
    

    同时

    int x;
    

    类似于

    extern int x;
    

    因为命名空间范围内的非const 声明暗示了外部链接。 (在最后一种情况下,它们实际上并不等价。extern 以及显式指定外部链接会生成对象的声明,而不是定义 .)

    请注意,这是特定于 C++ 的。在 C 中,const 不会更改隐含的链接。 原因是 C++ 委员会希望你能够编写

    const int x = 5;
    

    在标题中。在 C 中,包含在多个文件中的标头会导致链接器错误,因为您将多次定义同一个对象。

    【讨论】:

      【解决方案2】:

      从当前的 C++ 标准...

      7.1.1 存储类说明符

      7) 在没有存储类说明符的命名空间范围内声明的名称具有外部链接,除非它由于先前的声明而具有内部链接并且如果它没有声明为 const。 声明为 const 且未显式声明为 extern 的对象具有内部链接。

      3.5 程序与联动

      2) 当名称具有内部链接时,它所表示的实体可以由同一翻译单元中其他范围的名称引用。

      预处理器使头文件中定义的内容包含在当前翻译单元中。

      【讨论】:

        【解决方案3】:

        这样做时,您会在每个目标文件中为标题中的每个常量创建一个单独的const 变量。这不是问题,因为他们是const

        【讨论】:

        • 每个对象文件都有自己的“定义”吗
        【解决方案4】:

        真正的原因:因为#define是邪恶的,需要死。

        #define 的某些用法可以替换为内联函数。一些 - 带有const 变量声明。由于#define 往往在头文件中,用consts 替换那些更好的工作。因此,“consts 在默认情况下是静态的”规则。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-01-04
          • 1970-01-01
          • 1970-01-01
          • 2020-07-05
          • 2017-06-12
          • 1970-01-01
          • 2020-03-11
          相关资源
          最近更新 更多