假设我有,或者将要写,一组相关的函数。假设它们与数学有关。在组织方面,我应该:
编写这些函数,并将它们放在我的MyMath命名空间中,并通过MyMath::XYZ()引用它们 创建一个名为MyMath的类,并使这些方法是静态的,并引用类似的MyMath::XYZ()
为什么我要选择其中一种来组织我的软件呢?
假设我有,或者将要写,一组相关的函数。假设它们与数学有关。在组织方面,我应该:
编写这些函数,并将它们放在我的MyMath命名空间中,并通过MyMath::XYZ()引用它们 创建一个名为MyMath的类,并使这些方法是静态的,并引用类似的MyMath::XYZ()
为什么我要选择其中一种来组织我的软件呢?
当前回答
你应该使用命名空间,因为命名空间比类有很多优点:
您不必在同一个头文件中定义所有内容 您不需要在头文件中公开所有实现 你不能使用类成员;可以使用名称空间成员 不能使用类,尽管使用名称空间通常不是一个好主意 使用类意味着在实际上没有对象时创建某个对象
在我看来,静态成员被过度使用了。在大多数情况下,它们并不是真正必要的。静态成员函数可能更适合作为文件作用域函数,而静态数据成员只是全局对象,只是有一个更好的、不应有的声誉。
其他回答
如果需要静态数据,请使用静态方法。 如果它们是模板函数,并且您希望能够为所有函数一起指定一组模板形参,那么可以在模板类中使用静态方法。
否则,请使用命名空间函数。
对于这些评论:是的,静态方法和静态数据往往被过度使用。这就是为什么我只提供了两个相关的场景,我认为它们会有所帮助。在OP的特定示例(一组数学例程)中,如果他想要指定参数的能力——例如,核心数据类型和输出精度——将应用于所有例程,他可能会这样做:
template<typename T, int decimalPlaces>
class MyMath
{
// routines operate on datatype T, preserving at least decimalPlaces precision
};
// math routines for manufacturing calculations
typedef MyMath<double, 4> CAMMath;
// math routines for on-screen displays
typedef MyMath<float, 2> PreviewMath;
如果您不需要这样做,那么无论如何都要使用名称空间。
我想总结并补充其他答案。此外,我的视角是只看头部的世界。
名称空间
优点:
命名层次结构的简单解决方案 它们没有语义,所以读起来更简单 可以存在于不同的文件中(头文件) 可以扩展 诽谤联盟 可以定义快捷方式(使用)。 很好地与操作符过载 可以用于品牌(你可以设计你的代码并在上面放置一个名称空间)
缺点:
一切都是公开的 私有的东西需要未命名的命名空间,所以它不是显式的 ADL(是的,有些人鄙视ADL) 可以扩展(这可能是一件坏事,特别是与ADL结合使用时,扩展名称空间会改变现有代码的语义) 函数需要按使用顺序定义(或声明)
具有静态方法的类
优点:
can have private components (function, variables) and they are explicitly marked. classes can be friended can be type-parametrized (templates) can be template parameters themselves can be instantiated can be passed to functions (static functions behave like non-static method by default). it is easier to find patterns and go from groups of independent functions and convert them to a proper class (eventually with non static members) dependencies among classes is well defined functions (the static method) can be defined in any order
缺点:
没有诽谤联盟 不能扩展 到处都需要关键字static(取笑语言的机会) 单独解决命名问题有点过头了。在这种情况下很难阅读。 函数(静态方法)总是需要限定(myclassspace::fun)。没有办法声明快捷方式(使用)。 几乎无用的操作过载,需要复杂的朋友机制。 不能用于打品牌。 你要记得以;:)
总而言之,带有静态方法的类是更好的代码单元,允许更多的元编程,除了ADL和一些语法怪才之外,它们可以复制名称空间的所有功能,但有时它们可能会过度使用。
像Bloomberg这样的公司更喜欢类而不是名称空间。 如果你不喜欢ADL或操作符重载,带静态方法的类是最好的选择。
在我看来,如果将命名空间和类集成成同一枚硬币的两面,那就太好了。 例如,如果方法默认是静态的,则将语言中的命名空间标识为类。 然后能够将它们作为模板参数使用。 我不确定用ADL做什么(可能它可以被限制为符号运算符函数,例如operatorX,这是运算符重载和ADL的最初动机)
有很多人不同意我的观点,但我是这样看的:
类本质上是某种对象的定义。静态方法应该定义与该对象定义密切相关的操作。
如果你只是要有一组相关的函数,而不与底层对象或一种对象的定义相关联,那么我会说只使用名称空间。对我来说,从概念上讲,这更合理。
例如,在你的情况下,问自己,“MyMath是什么?”如果MyMath没有定义一种对象,那么我会说:不要让它成为类。
但就像我说的,我知道有很多人(甚至激烈地)不同意我的观点(特别是Java和c#开发人员)。
我更喜欢名称空间,这样可以在实现文件中的匿名名称空间中拥有私有数据(因此与私有成员相反,它根本不必显示在头文件中)。另一个好处是,通过使用命名空间,方法的客户端可以选择不指定MyMath::
为什么我要选择其中一种来组织我的软件呢?
如果您使用名称空间,您将经常遇到一个语言缺陷,即相互调用的函数必须以特定的顺序列出,因为c++无法在文件中看到进一步的定义。
如果使用类,则不会出现此缺陷。
在类中包装实现函数比维护所有实现函数的声明或以非自然的顺序放置实现函数以使其易于编译更简单。