如何正确使用命名空间以避免名称冲突?

5

我对C++命名空间的正确使用有些困惑。很明显,它们可以帮助避免冲突(名称冲突),但是当涉及到using关键字时,就不再清楚了。我的意思是,假设我将我的代码的一部分放入一个命名空间中,并创建一个类,比如说

namespace my
{
    class vector { ... };
}

当我使用它时,我不想一直打 "my::vector",所以我想用 "using namespace my"。但是,我最终可能需要来自 "std" 命名空间的某些东西,这时我希望同时使用 "using namespace std",但这又会让我回到最初的命名冲突问题。
我知道可以只“导入”我需要的功能,比如 "using std::set",但在这种情况下,像我一样经常使用两个命名空间,完全导入标准命名空间 "std" 和 "my" 命名空间似乎更自然。
这是否意味着即使使用命名空间,我仍应考虑为我的类型命名非通用名称?还是说使用 "using namespace" 是一个错误,我应该始终打出 "my::vector"?谢谢。
嗯,我应该澄清一下,这更多是关于可读性而非输入的问题。到处都有 "::" 看起来对我来说很奇怪。我知道这是一个品味和习惯的问题,但无论如何。

7
我不想一直打my::vector。为什么?完全限定名称(或者对于长的命名空间名字使用命名空间别名)有助于使您的代码更清晰易懂(没有猜测名称来自哪里)。它还可以帮助您避免使用using指令时可能发生的棘手名称查找问题(尤其是using namespace std;)。这种名称查找问题不会经常发生,但当它们发生时,诊断起来可能很困难。我在Stack Overflow上回答过许多关于由using namespace std;引起的问题的困难问题。 - James McNellis
1
@James:主要的动机不是太在意打字,而更多的是关于可读性。或许这是一种口味和习惯问题,但目前到处都充斥着::让我觉得阅读起来更加困难。 - Roman L
@James:如果是嵌套命名空间,情况会变得更糟,例如my::db::helpers::class(随意举例,请勿过于认真),在我看来真的很糟糕 :) - Roman L
4
问题可以通过 namespace dbhelp = my::db::helpers; 来解决。该语句为给命名空间 my::db::helpers 起了一个别名 dbhelp,以便更方便地使用其中的函数和变量。 - Fred Foo
3
由于命名空间别名和使用声明/指令,它仍然比我的_db_helpers_class容易 (在没有命名空间的可管理代码中),尽管如此,我经常希望你可以在那里使用句点而不是双冒号。 - Fred Nurk
显示剩余5条评论
3个回答

10
当我使用my::vector时,会显得很繁琐,所以我想使用using namespace my来简化。但是,当我需要使用std命名空间的内容时,我也想同时使用using namespace std,但这会导致最初的名称冲突问题再次出现。 是的,这确实会让你回到最初的名称冲突问题。这就是为什么你应该只在源文件中稀少地使用using namespace ...;指令,而从不在头文件中使用。
这是否意味着即使使用命名空间,我仍应考虑给我的类型命名为非常见名称? 不需要,命名空间的发明就是为了避免这个问题。
还是说using namespace是一个错误,我应该总是输入my::vector? 你可以使用using namespace ...;或using ...;指令,直到出现冲突为止。这意味着当你确实有冲突时,在某些地方你将不得不通过显式限定名称来编写“不自然”的代码。 实际上,当你处理短命名空间名称(即std)时,你可以一直明确地输入它们。一周左右后,你甚至意识不到自己正在输入它们。

5
理想情况下,如果要使用using指令,应该在函数作用域内使用,这样易于跟踪。 - James McNellis
2
+1 是指“你甚至不会注意到自己正在输入它。” 我已经停止在文件范围内使用 using namespace,并且很少输入 using 指令(只针对模块或函数中经常出现的标准类型)。 - Fred Foo
@James:对于过长的命名空间,我也确实会采用这种方法! - André Caron

4
如果你的代码同时使用了 std::vectormy::vector,那么始终使用完整名称是最佳选择。

0

如果你立即再次打开命名空间,为什么要在第一时间将其放入命名空间中呢?你可以将类放在全局命名空间中!

对于那些没有注意到文件顶部的using指令的人来说,vector不是std::vector会非常令人困惑。这本身就是编写my::vector的原因之一!

对我来说,看到像std::vector和std::list这样的名称实际上提高了可读性,因为我立即知道这些名称的含义。


1
当然,我不会在所有地方都重新打开它,主要是在使用这些命名空间中的类的.cpp文件中,因此它与使它们全局不完全相同。 我仍然不同意“::”,因为我发现它们在视觉上太过分散注意力了。 实际上,我同意@Fred Nurk的观点,即能够使用句点代替冒号(如Java / Python / C#中)将非常有帮助。 - Roman L

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接