3

我遇到了一些关于我希望修复的代码风格的怪癖,即命名空间的使用。首先让我说,我目前是我特定项目的唯一软件工程师,并且无法获得更高级别的工程师来指导和帮助我。我发现这特别令人担忧,因为我担心我正在开发非常hacky的做法,当我在不久的将来尝试换工作时,这会让我笑出房间。

最近我一直在关注并遵守谷歌风格指南。当我得知我一直在做“使用命名空间标准”的过程时,我有点震惊。不赞成。一般来说,我的大多数项目都相对较小,几乎没有机会重用我的课程。然而,现在我已经做了更多的研究和学习,我意识到为什么我的做法不受欢迎,我正在寻求改进我使用命名空间和范围运算符的方式。结果,我有以下问题:

  1. 什么时候最好定义一个新的命名空间?我知道这是一个奇怪的问题,而且我知道不属于某个类的函数或变量可以在命名空间中组合在一起。但是,假设我有一个仅由类组成的程序。不定义命名空间是不好的做法吗?或者是否应该为项目单独创建一个新的命名空间,以防以后有人想与它交互?

  2. 我知道这已经引起了令人作呕的争论,但是什么时候使用“std::”比较好?我问是因为我最近读到了如何更好地使用 C 标准库的“包装”版本(例如,cstdlib 与 stdlib.h)。我更改了一些源代码以进行实验。我立刻觉得奇怪的是,G++ 没有因为我没有使用 std::printf() 而不是 printf() 而对我大喊大叫。我现在的问题是在显式范围放置方面我应该在哪里停止?例如,编译器不会对我大喊 size_t 或 uint8_t,我是否也必须在它们前面放置“std::”?什么被认为是最佳实践?

  3. 是否考虑仅在您正在使用的功能上调用“使用”?也就是说,我说的是我有一个班级并且会做类似“使用std :: endl;”之类的事情。在实现特定类的 .cpp 文件中。

编辑添加第四个问题: 4. 为派生类编写代码时,无论何时调用基类中的函数,即使基类中的函数不是虚拟的,执行“Baseclass::function()”是否有意义并且不能超载?这会阻碍或提高可读性吗?

感谢所有的帮助。我发现这个网站是一个很好的资源!

4

3 回答 3

2

这些做法多年来一直对我很有帮助。希望你觉得这很有帮助。

1) 命名空间是一种将相似事物保持在一起的组织技术,通常用于可发现性并避免与其他代码的名称冲突。当您使用具有智能感知功能的 IDE 时,它们可以提供很大的帮助,使编码变得容易,而无需返回文档来查找内容。过于细粒度的命名空间可能对您的代码有害,就像没有命名空间一样。虽然这里没有硬性规定,但如果您一直在为少于 3-4 个项目的组创建新的命名空间,那么您可能做得过火了。您通常也不会在 .cpp 文件中定义新的命名空间,因为这是唯一可以看到它的文件。我很少看到另一个极端的例子。

使用模板时,一切都在标头中,我喜欢在主命名空间下创建一个“详细信息”命名空间,以将模板库的“私有”类与人们实际期望使用的东西隔离开来。还有其他实现类似结果的方法可以提供更好的封装,但它们也需要更多的工作来维护。

2) using 语句通常应该隔离在 C++ 文件中,而不是放在标题中,否则您很快就会忘记在大型项目中“使用”的内容。同样,如果您的标头不隐式依赖于 using 语句,则最好是可移植性和可维护性。您可以通过将 using 语句紧跟include 语句之后来避免这种情况。

// main.cpp
#include "myheader1.h" // can't see using namespace std, ok.

using namespace std;

// Does this have std:: in front of everything that needs it? 
// Maybe. Compiler won't tell me...
#include "myheader2.h" 

永远不要将 using 语句放在开放的命名空间内。也就是说,除非你真的,真的想让人们头晕目眩。这可能不会像您(或下一个人)期望的那样工作。

namespace A { ... }

namespace B {
  using namespace A; // Don't do it!
}

在某些情况下,对于绝对无处不在的命名空间,我看到人们将 using 语句放在预编译的头文件中(这只是 VC++ 的事情吗?)。我觉得这是可以忍受的,因为它们通常是一小段代码的本地代码,尽管即使在那里我认为这是一个延伸。它可以方便上面提到的头依赖问题。

3)这种做法可能会令人讨厌,因为你会发现你必须继续返回“另一件事”并且它可能会令人困惑(“等等,对于这个文件,我是否使用了 math::vector,physics ::vector 还是 std::vector?”)。如果由于冲突问题而无法使用整个命名空间,最好至少明确其中一个命名空间。如果有很多重叠,并且可能对两者都明确。

在极少数情况下,对于深度嵌套的命名空间,编写如下内容可能很有用:

using namespace this::thing::is::ridiculous::someone::should::trim::it = ludicrous;

这允许使用一个简短的名字来引用命名空间,例如

auto p = new ludicrous::SomeClass();

如果你打算这样做,你应该在整个代码库中为你这样做的命名空间建立一致的约定。如果您在 3 个不同的地方使用 3 个不同的名称,您只会使代码的可读性降低。

于 2013-06-12T06:33:01.883 回答
1
  1. 任何设计为可重用的东西都应该使用命名空间。任何名称可能会发生名称冲突的东西都应该使用命名空间,这几乎意味着任何东西。对于较小的项目,它并不重要,但总的来说,一切都应该进入某种命名空间。

  2. 基于 C++ 标准,来自 C++ 标准标头的任何内容都将位于 namespace 中std。它们也可能被拉入全局命名空间。因此,您应该更喜欢使用std::printforstd::uint8_t等​​以获得最大的可移植性。

  3. 这是一个偏好问题。对于std::命名空间中的基本内容,我宁愿个人明确,因为要输入的字符很少。对于高度嵌套的命名空间名称(例如需要经过 3 个以上命名空间的某些部分boost),using则更有意义。

于 2013-06-12T03:34:52.600 回答
0

例如,我的偏好是使用 std::cout,即 ::FunctionName()。1. 在我看来,这使得代码的审阅者/读者的使用变得明显/明确。
2.“使用命名空间”最终包括该命名空间的所有类,因此可能会导致与您的类/函数名称发生冲突。3. 如果一个人知道任何一个正在开发的东西都是一个库,在它自己的命名空间中创建它是必须的。4. 对于不会开发/与第三方接口的类,我不会为命名空间而烦恼。

让我知道这是否回答了您的问题。否则回来了解更多细节。

于 2013-06-12T03:51:46.180 回答