c++命名空间新手需要帮助

C++ Namespace Noob Needs Assistance

本文关键字:帮助 新手 命名空间 c++      更新时间:2023-10-16

我遇到了一些关于我的代码风格的怪癖,我希望修复,即与名称空间的使用。首先,我想说的是,我目前是这个项目中唯一的软件工程师,没有更高级的工程师来指导和帮助我。我觉得这一点特别令人担忧,因为我担心自己正在养成一些非常糟糕的做法,在不久的将来,当我试图换工作时,这些做法会让我被嘲笑出房间。

最近我一直在遵循并遵守谷歌的风格指南。当我得知"使用命名空间std"的过程不受欢迎时,我感到有点震惊。总的来说,我的大多数项目都相对较小,几乎没有机会重用我的类。然而,现在我做了更多的研究和学习,我意识到为什么我的实践不受欢迎,我正在寻求改进我使用名称空间和作用域操作符的方式。因此,我有以下问题:

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

  2. 我知道这已经引起了争论,但是什么时候使用"std::"是好的呢?我问这个问题是因为我最近读了一篇关于如何更好地使用C标准库的"包装"版本的文章(例如,cstdlib与stdlib.h)。我修改了一些源代码进行实验。我立刻发现奇怪的是,c++并没有因为我没有使用std::printf()而只是使用printf()而对我大喊大叫。我现在的问题是,就显式作用域的位置而言,我应该在哪里停止?例如,编译器不会对我大喊关于size_t或uint8_t,我是否必须将"std::"放在前面?什么是最佳实践?

  3. 是否考虑仅对您正在使用的函数调用"正在使用"?也就是说,我说的是这样一种情况,我有一个类,并将在实现特定类的.cpp文件中执行类似"使用std::endl;"的操作。

编辑添加第四个问题:4. 当为派生类编写代码时,无论何时从基类调用函数,即使来自基类的函数不是虚的,也不能重载,这样做"Baseclass::function()"是否有意义?这会阻碍还是提高可读性?

谢谢你的帮助。我发现这个网站是一个伟大的资源!

这些做法多年来使我受益匪浅。希望对你有帮助。

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个不同的名称,只会使代码的可读性降低。

  1. 任何设计为可重用的东西都应该使用名称空间。任何有可能发生名称冲突的名称都应该使用名称空间,这意味着几乎任何东西。对于较小的项目,它的影响较小,但一般来说,所有内容都应该放入某种命名空间中。

  2. 基于c++标准,任何来自c++标准头的内容都将位于命名空间std中。它们也可以被拉到全局命名空间中。因此,为了获得最大的可移植性,您应该更倾向于使用std::printfstd::uint8_t等。

  3. 这是个人喜好的问题。对于std::名称空间中的基本内容,我个人宁愿是显式的,因为要输入的字符很少。对于高度嵌套的名称空间名称(如boost的某些部分,其中有3个以上的名称空间要处理),那么using更有意义。

我倾向于使用std::cout,即::FunctionName()。1. 在我看来,这使得代码的审阅者/读者可以明显/明确地使用它。
2. "正在使用的名称空间"最终包括该名称空间的所有类,因此可能导致与类/函数名冲突。3.如果知道正在开发的是一个库,就必须在自己的名称空间中创建它。4. 对于不打算开发或与第三方接口的类,我不会为命名空间而烦恼。

让我知道这是否回答了你的问题。