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
。内容合并在一起。它纯粹是一种减少混乱的机制(限定名称查找)。
stoi
是如何成为std
的成员的。我可以理解宏,如果我打开那个文件(字符串),我看不到它发生在哪里。
命名空间可以跨越多个文件。很可能您找不到namespace std
,因为它位于<string>
包含的文件中。例如,在 g++ 的库实现中,<string>
包括 <bits/basic_string.h>
,它在 std
命名空间内声明了 namespace std
和 stoi
。
如果有帮助,请记住,当您#include
一个文件时,结果是该文件被字面意思复制并粘贴到源代码中。因此,当您多次出现相同的命名空间时,使用多个文件与单个文件并没有真正的区别。
【参考方案1】:
可以添加命名空间。例如,在一个文件中,您可能有:
namespace myspace
int f();
在另一个方面:
namespace myspace
void g();
现在f
和g
都是命名空间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++ 中的头文件和命名空间的主要内容,如果未能解决你的问题,请参考以下文章
spring16-----XML命名空间和Spring配置文件中的头