【问题标题】:Header files and namespaces in C++C++ 中的头文件和命名空间
【发布时间】:2019-04-30 21:32:29
【问题描述】:

我在处理头文件和命名空间时遇到了问题。如果我们在命名空间中定义函数,那么我们可以使用该命名空间的名称作为标识符。

这没问题,但真正令人困惑的是 C++ 中的大多数函数(在 不同 头文件中声明)都在 std 命名空间中。

现在是头文件里面的名字空间还是名字空间里面的头文件?

如果命名空间在每个头文件中,那么如何使函数(在头文件中声明并完全实现)成为该预定义命名空间的成员?

一个具体的例子:

当我尝试在 C++ 中使用 string 时,我使用 #include <string> 但随后我必须使用标识符来调用函数(如 std ::stoi)。

现在,当我打开头文件string 时,我看到stoi 在头文件string 中完全实现。那么这个函数如何成为std 命名空间的成员,因为在string 头文件中我没有在任何地方看到std,也没有明确地将它设为std 命名空间的成员。

我的问题可能非常基本,但我在任何地方都找不到答案。简单地在命名空间中声明一个函数然后使用它很简单,但是一个在头文件中声明和实现的函数,该函数如何成为任何命名空间的成员,一个命名空间如何具有来自不同头文件的函数?

如果有人告诉我stoi 是如何成为std 的成员的就足够了。剩下的我自己做。

【问题讨论】:

  • 每个头文件声明相同的命名空间,例如namespace std。内容合并在一起。它纯粹是一种减少混乱的机制(限定名称查找)。
  • 中必须有 std:: 但这些文件是实现定义的。头文件和命名空间是不相关的。包括只是粘贴代码。
  • 我希望有人告诉我stoi 是如何成为std 的成员的。我可以理解宏,如果我打开那个文件(字符串),我看不到它发生在哪里。
  • 命名空间可以跨越多个文件。很可能您找不到namespace std,因为它位于<string> 包含的文件中。例如,在 g++ 的库实现中,<string> 包括 <bits/basic_string.h>,它在 std 命名空间内声明了 namespace stdstoi
  • 如果有帮助,请记住,当您#include 一个文件时,结果是该文件被字面意思复制并粘贴到源代码中。因此,当您多次出现相同的命名空间时,使用多个文件与单个文件并没有真正的区别。

标签: c++


【解决方案1】:

可以添加命名空间。例如,在一个文件中,您可能有:

  namespace myspace {
      int f();
  }

在另一个方面:

  namespace myspace {
      void g();
  }

现在fg 都是命名空间myspace 中的函数。如果您愿意,您还可以在上述代码中提供函数的定义。或者在一个实现文件中你可以这样做:

  namespace myspace {
      int f() {
           return 42;
      }
  }

【讨论】:

    【解决方案2】:

    在 Visual Studio 中,<string> 标头有这一行:

    _STD_BEGIN
    

    它是一个宏定义为:

    #define _STD_BEGIN  namespace std {
    

    所以命名空间是在头文件中指定的。然后在第 179 行左右找到stoi

    inline int stoi(const string& _Str, size_t *_Idx = nullptr,
    

    还有更远的地方:

    _STD_END
    

    扩展为:

    }
    

    std 命名空间的末尾。

    【讨论】:

    • 注意:以下划线开头后跟大写字母的标识符(如_STD_BEGIN_STD_END)是保留的。不要在自己的代码中使用它们,除非您正在编写编译器或标准库实现并且您知道自己在做什么。
    猜你喜欢
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    相关资源
    最近更新 更多