C++ 中的头文件和命名空间

Posted

技术标签:

【中文标题】C++ 中的头文件和命名空间【英文标题】:Header files and namespaces in 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 一个文件时,结果是该文件被字面意思复制并粘贴到源代码中。因此,当您多次出现相同的命名空间时,使用多个文件与单个文件并没有真正的区别。 【参考方案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)是保留的。不要在自己的代码中使用它们,除非您正在编写编译器或标准库实现并且您知道自己在做什么。

以上是关于C++ 中的头文件和命名空间的主要内容,如果未能解决你的问题,请参考以下文章

1开始学习C++

spring16-----XML命名空间和Spring配置文件中的头

C++:“类命名空间”? [复制]

C++中的cmath头文件

什么时候适合在 C++ 中使用静态(通过未命名的命名空间)?

php--命名空间