既有类又有命名空间?
这个问题是关于一个我越来越多地使用的模式:为相关概念同时创建类和命名空间。我认为这主要是由于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中的自由函数bar,即::Foo::bar(),还是在命名空间::Foo::Foo::bar中的类Foo的成员函数。
而像::Foo::Foo::bar这样的名称仍然不太好。
目前我正在做的是:
在名称中不需要使用任何后缀或指示符:
namespace Foo_ns {
class Foo {
...
};
}
主要是因为我通常先创建类,然后意识到一个命名空间会很好。
我想知道是否应该恢复我多年未使用的命名约定:使用 _c 表示类,_ns 表示命名空间:
namespace Foo_ns {
class Foo_c {
...
};
}
详情:
我不会重复我之前说过的,但我会补充一些细节。
我知道使用命名空间而不是类的最实用原因是,您可以在命名空间中进行自由函数的前向声明,但是您不能对类的某些方法进行前向声明。也就是说,使用类时,您必须全部或不声明。而对于自由函数,特别是命名空间中的自由函数,您可以逐个声明。部分内容可以在不同的头文件中声明。您可以仅使用一个或两个函数的前向声明,而不是#包含庞大的头文件库以包含大量的类。等等。
(例如,请参见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。
(顺便说一句,我倾向于使用带下划线和大写字母开头的类名,而不是驼峰命名法。)
如果有意义,我可能会省略命名空间上的 _ns 后缀,例如当命名空间和类不需要具有相同的名称时。
我不喜欢让它们具有相同的名称。考虑一个命名空间 foo 中的类 Foo 的构造函数:
:: Foo :: Foo :: Foo () VS :: Foo_ns :: Foo :: Foo ()
后者并没有好到哪里去,但要清晰一些。
我认为我通常会独立创建类,而不将其嵌套在命名空间中。事实上,我可能会添加一些静态方法,然后才意识到嵌套在命名空间中的类会更好。此时,重构可能很麻烦,我有时会创建转发函数,从类静态方法转发到命名空间中的自由函数,反之亦然。这使我后悔没有从第一步直接跳转到命名空间内的类。
结论
我目前的最佳做法是Foo_ns / Foo_ns :: Foo,即
namespace Foo_ns {
class Foo {
...
};
}
我会感激任何建议,任何改进。
或者说,我这样做是不是就是有问题?
foo::bar()
与Foo::bar()
的区别非常明显。 - Voo