c++ - 类与命名空间,还是类与命名空间?

标签 c++ class namespaces static-methods non-member-functions

就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center为指导。




8年前关闭。




类和命名空间?

这个问题是关于我看到自己越来越多地使用的一种模式:同时拥有一个类和一个用于相关概念的命名空间。我认为这主要是由 C++ 语言工件激发的,但并非完全如此。

我想最重要的问题是:这是个好主意吗?拥有相关概念的类和命名空间?

低级问题:

做到这一点的最佳方法是什么?

嵌套在命名空间中的类?:

namespace Foo_Namespace {
   class Foo_Class {
       ...
   };
}

还是单独的、对等的、类和命名空间的?:
class Foo_Class {
    ...
};
namespace Foo_Namespace {
   // non-class free functions, etc.
}

我必须承认我倾向于在命名空间中嵌套类。
即使它会导致丑陋的名字。
但即使我这样做,我应该使用什么命名约定:

以下太长,导致名称非常难看 Foo_Namespace::Foo_Class
namespace Foo_Namespace {
   class Foo_Class {
       ...
   };
}

不必在名称中使用任何后缀或指示符:
namespace Foo {
   class Foo {
       ...
   };
}

但后来我发现自己不确定,当我查看 Foo::bar() 时,它是否是命名空间::Foo 中的自由函数栏,即::Foo::bar() 或命名空间中 Foo 类中的成员函数::Foo::Foo::bar()。

像::Foo::Foo::bar 这样的名字仍然不是,嗯,很好。

目前我正在做

不必在名称中使用任何后缀或指示符:
namespace Foo_ns {
   class Foo {
       ...
   };
}

主要是因为我通常先创建类,然后才意识到命名空间会很好。

我想知道我是否应该恢复我多年未使用的命名约定:_c 表示类,_ns 表示命名空间:
namespace Foo_ns {
   class Foo_c {
       ...
   };
}

详情:

我不会重复我上面所说的,但我会补充一点。

我所知道的除了类之外还使用命名空间的最实际原因是,您可以在命名空间中对自由函数进行前向声明,但不允许对类的某些方法进行前向声明。即对于一个类,你必须要么全部声明,要么什么都不声明。而对于一般的自由函数,特别是命名空间中的自由函数,您可以将其声明为零碎的。部件可以在不同的头文件中声明。您可以为一两个函数使用前向声明,而不是为大量类#include 大量头文件库。等

(例如,请参阅 http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Forward_Declarations ,尽管 Google 完全反对前向声明而不是包含标题。)

另一个原因是命名空间允许类本身保持较小。

类的最大优点是类可以传递给模板,而命名空间则不能。

我更喜欢将类嵌套在命名空间 Foo_ns/Foo_ns::Foo_c 中,而不是将它们作为同级 Foo_ns/Foo_c,因为通常一个类需要帮助类,例如Foo_ns/Foo_ns::Foo_c/Foo_ns::Foo_Helper_c。如果类和命名空间是对等的,那么有 Foo_ns/Foo_c 但有 Foo_ns::Foo_Helper_c 似乎很奇怪。

我喜欢命名空间,因为我同意 Andrei Alexandresciu 的观点:http://laser.inf.ethz.ch/2012/slides/Alexandrescu/1-C++%20course%20parts%201%20and%202.pdf
 Class methods vs. free functions

 • Conventional wisdom: methods are cool, free functions are so 1960s
 • Yet:
   ◦ Free functions improve encapsulation over methods
   ◦ Free functions may be more general
   ◦ Free functions decouple better
   ◦ Free functions support conversions on their left-hand argument

  Surprising fact #2

    Making a function a method should be
    your last, not first, choice

  (c) 2012– Andrei Alexandrescu. 32 / 59

最好创建自由函数而不是类中的方法。

但有时只需要使用类 - 例如用于模板。

命名约定明智

我过去使用过 Foo_ns/Foo_ns::Foo_c

我现在正在使用 Foo_ns/Foo_ns::Foo

(顺便说一句,我倾向于使用 Class_Names_With_Underscores_and_Initial_Caps,而不是 CamelCase。)

如果有意义,我可能会省略命名空间上的 _ns 后缀 - 例如其中命名空间和类不需要具有相同的名称。

我不喜欢让它们具有相同的名称。考虑命名空间 foo 内的类 Foo 的构造函数:

::Foo::Foo::Foo()
对比
::Foo_ns::Foo::Foo()

后者并没有好多少,但不那么令人困惑。

我认为我通常自己创建类,而不将它嵌套在命名空间中。
事实上,在我意识到嵌套在命名空间中的类会更好之前,我可能添加了一些静态方法。到了那个阶段,重构可能会很痛苦,我有时最终会创建转发函数,从类静态方法转发到命名空间中的自由函数,反之亦然。这让我后悔 bot 直接从第 1 步跳转到命名空间的类。

结论

我目前的 BKM 是 Foo_ns/Foo_ns::Foo,即
namespace Foo_ns {
   class Foo { 
   ...
   };
}

我很感激任何建议,任何改进。

或者我只是因为这样做而崩溃?

最佳答案

我建议将您的类放在具有相关功能的命名空间中。造成这种情况的一个重要原因是 argument-dependent lookup (ADL)。当您调用具有类类型参数的非成员函数时,将在该类的封闭命名空间中查找函数名称。所以,如果你有,请说:

namespace foo {
  class bar { };
  void baz(bar);
}

如果您想调用 baz ,您不需要明确给出它所包含的命名空间,您可以简单地执行以下操作:
foo::bar x;
baz(x);

不合格baz ,编译器仍然找到该函数,因为它位于包含其参数类型的命名空间中。这样,C++ 将类的封闭命名空间的内容视为该类接口(interface)的一部分。以这种方式将属于类接口(interface)的函数实现为非成员非友元函数,从而允许 ADL 找到该函数,increases encapsulation .如果函数不需要访问类的内部结构,不要让它成为该类的成员——而是将它放在与该类相同的命名空间中。

然而,您的命名空间与您的类同名是值得怀疑的。通常一个命名空间中会有多个类,即使没有,名称也会不同。命名空间的名称应该描述其内容,而不仅仅是其中的单个类。

关于c++ - 类与命名空间,还是类与命名空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14418959/

相关文章:

ruby - 使用 let() 辅助函数时 Rspec 中的命名空间问题

python - 无法在 ios (El Capitan) 中安装 mxnet 并运行 python (2.7) 示例

c++ - 是否隐藏了 void* 参数的名称?

c++ - cpp 中十六进制模式的大小

javascript - ID 和带有数字的类 - 好还是坏?

javascript - node.js 中的命名空间导入

c# - 是否可以构建面向 Linux 和 Windows 的 .Net Core C++/CLI 应用程序

c++ - 将 "getline"与数组一起使用

c++ - 有什么办法可以在C++中 “uninclude”文件?

html - 水平对齐同名的2个类