问题可能很简单(可能重复)。
据我了解,一个C / C ++头文件(其中带有using namespace
)在被其他源文件使用时,将被直接复制到#include
指令所在的位置在该源文件中。
另外,假设源文件使用相对大量的include伪指令,并且整个标准库可能有几个“重新定义”(仅针对不同的实现)。
这是主要问题:如果源文件中没有using namespace
语句,我如何知道源文件中任何时候我正在使用哪个名称空间?
我正在阅读源文件,不知道正在使用哪个名称空间。
可以使用::std::getline()
之类的东西来覆盖名称空间的聪明之处。
如果没有简单的方法来确定名称空间,是否重构这些文件是否公平,例如用string
替换为::std::string
?
答案 0 :(得分:3)
如果没有using namespace ...
指令,则说明您未使用任何名称空间。通常,您的代码应使用全名来引用标准库中的内容,例如std::cout
,std::get_line()
,std::string
。
是的,您可以为自己保存一些键入内容,但会损失一些清晰度,有时甚至会出现神秘的编译失败,或者更糟糕的是,using namespace std;
会导致运行时失败。之后,您不必在标准库中的事物名称之前放置std::
:cout
,get_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();
}
这将分别在命名空间f
和foo
中声明两个函数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上则没有。 )