使用命名空间及其包含内容

时间:2019-01-27 16:59:27

标签: c++ namespaces include

问题可能很简单(可能重复)。

据我了解,一个C / C ++头文件(其中带有using namespace)在被其他源文件使用时,将被直接复制到#include指令所在的位置在该源文件中。

另外,假设源文件使用相对大量的include伪指令,并且整个标准库可能有几个“重新定义”(仅针对不同的实现)。

这是主要问题:如果源文件中没有using namespace语句,我如何知道源文件中任何时候我正在使用哪个名称空间?

我正在阅读源文件,不知道正在使用哪个名称空间。

可以使用::std::getline()之类的东西来覆盖名称空间的聪明之处。

如果没有简单的方法来确定名称空间,是否重构这些文件是否公平,例如用string替换为::std::string

4 个答案:

答案 0 :(得分:3)

如果没有using namespace ...指令,则说明您未使用任何名称空间。通常,您的代码应使用全名来引用标准库中的内容,例如std::coutstd::get_line()std::string

是的,您可以为自己保存一些键入内容,但会损失一些清晰度,有时甚至会出现神秘的编译失败,或者更糟糕的是,using namespace std;会导致运行时失败。之后,您不必在标准库中的事物名称之前放置std::coutget_line()string。 using指令将这些名称以及您可能不感兴趣的污泥放入全局名称空间。

如果您使用using namespace std;之类的名称,则它应仅出现在源文件中,从不出现在标题中。这样,您可以通过查看文件顶部来确定已“使用”了哪些名称空间。您无需使用指令就可以在所有标头中跟踪是否有误。

答案 1 :(得分:1)

using namespace并不意味着您当前正在使用此特定名称空间。这意味着该名称空间中的所有类型,变量和函数现在都在此转换单元的全局名称空间中。因此,您可能有多个这样的语句。

这就是为什么头文件绝对不能使用using namespace的原因。没有比在头文件中使用std::string更简单的方法了,对于没有using namespace的名称空间,应该始终非常明确。

恐怕已经使用了using namespace xxx,所以无法找出xxx现在位于全局命名空间中。

答案 2 :(得分:1)

using namespace并没有达到您的期望...

如果要在命名空间中放置函数,类或变量,请按照以下方式进行操作:

namespace foo
{
    void f();
}
namespace bar
{
    void f();
}

这将分别在命名空间ffoo中声明两个函数bar。您将在头文件中找到相同的内容;如果没有如上所述指定名称空间,则函数/类/变量位于全局名称空间中。没什么。

using namespace现在允许您使用命名空间中的函数,而不必显式指定它:

// without:
foo::f();
bar::f();
f();      // unknown!

using namespace foo;
foo::f(); // still fine...
bar::f();
f();      // now you call foo::f

不过请注意,这是bad practice(链接指向名称空间std,但对 all 名称空间也适用)。

在头文件中,情况甚至更糟:无法再次撤消已声明的using namespace <whatever>的效果–因此,您将其强加到头文件的所有用户上,可能给其中一些用户带来很大麻烦。因此,请不要在头文件中使用它。

答案 3 :(得分:1)

我现在可以想到三种方法:

使用IDE :现代的开发环境应该能够(可能在插件的帮助下)在编辑时分析代码,并告诉您所标识的任何标识符的权威限定名称将鼠标悬停在上方。

如果您不使用IDE,这当然不是一个选择,有时甚至IDE可能会感到困惑,并为您提供错误的信息。

使用编译器进行猜测:如果您已经预感可能会使用哪个命名空间,则可以定义一些对象,通过限定名称引用它,并查看代码是否可以编译,例如:

const int Fnord = 1;
const int* Probe = &::solid::guess::Fnord;

一个警告是,如果涉及using namespace或匿名名称空间,它可能会产生误导性的结果。

使用预处理器:大多数编译器定义了一个预处理器宏,用于告诉您所使用的函数的名称,其中可能包括名称空间;例如,在MSVC上,__FUNCTION__会执行此操作。如果文件包含您知道将要执行的函数,则可以让该函数在运行时告诉您它的权威限定名称,如下所示:

int SomeFunction(void)
{
    printf("%s\n", __FUNCTION__);
}

如果您不能使用标准输出,则可以将值存储在变量中,然后使用调试器进行检查。

如果找不到这样的函数,请尝试使用自身的静态实例定义一个类,然后将代码放入构造函数中。

(很遗憾,我无法想到一种在编译时检查宏的值的方法; static_assert在我脑海中浮现出来,但是不能在函数内部使用,__FUNCTION__可以不能在外面使用。)

尽管该宏未标准化,并且可能不包含名称空间(或者可能根本不存在)。例如,在GCC上,__FUNCTION__仅会给您提供不合格的名称,而您将不得不使用__PRETTY_FUNCTION__

(从C99和C ++ 11开始,确实存在标准化的替代方法__func__,但是未指定函数名称的格式,并且可能包含或不包含名称空间。在GCC上则没有。 )