C++ 命名空间 + 函数与类上的静态方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1434937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Namespace + functions versus static methods on a class
提问by RobertL
Let's say I have, or am going to write, a set of related functions. Let's say they're math-related. Organizationally, should I:
假设我有或将要编写一组相关的函数。假设它们与数学有关。在组织上,我应该:
- Write these functions and put them in my
MyMath
namespace and refer to them viaMyMath::XYZ()
- Create a class called
MyMath
and make these methods static and refer to the similarlyMyMath::XYZ()
- 编写这些函数并将它们放在我的
MyMath
命名空间中并通过MyMath::XYZ()
- 创建一个名为的类
MyMath
并使这些方法静态并引用类似的MyMath::XYZ()
Why would I choose one over the other as a means of organizing my software?
为什么我会选择一种而不是另一种来组织我的软件?
回答by paercebal
By default, use namespaced functions.
默认情况下,使用命名空间函数。
Classes are to build objects, not to replace namespaces.
类是用来构建对象的,而不是用来替换命名空间的。
In Object Oriented code
在面向对象的代码中
Scott Meyers wrote a whole Item for his Effective C++ book on this topic, "Prefer non-member non-friend functions to member functions". I found an online reference to this principle in an article from Herb Sutter: http://www.gotw.ca/gotw/084.htm
Scott Meyers 为他关于这个主题的 Effective C++ 一书写了一个完整的条目,“Prefer non-member non-friend functions to member functions”。我在 Herb Sutter 的一篇文章中找到了对这个原则的在线参考:http://www.gotw.ca/gotw/084.htm
The important thing to know is that: In C++ functions in the same namespace as a class belong to that class' interface(because ADLwill search those functions when resolving function calls).
要知道的重要一点是:在与类相同的命名空间中的 C++ 函数属于该类的接口(因为ADL将在解析函数调用时搜索这些函数)。
Namespaced functions, unless declared "friend," have no access to the class' internals, whereas static methods have.
命名空间函数,除非声明为“朋友”,否则无法访问类的内部,而静态方法则可以。
This means, for example, that when maintaining your class, if you need to change your class' internals, you will need to search for side effects in all its methods, including the static ones.
这意味着,例如,在维护类时,如果需要更改类的内部结构,则需要在其所有方法中搜索副作用,包括静态方法。
Extension I
扩展一
Adding code to a class' interface.
将代码添加到类的接口。
In C#, you can add methods to a class even if you have no access to it. But in C++, this is impossible.
在 C# 中,即使您无法访问类,也可以向类添加方法。但在 C++ 中,这是不可能的。
But, still in C++, you can still add a namespaced function, even to a class someone wrote for you.
但是,仍然在 C++ 中,您仍然可以添加命名空间函数,甚至可以添加到某人为您编写的类中。
See from the other side, this is important when designing your code, because by putting your functions in a namespace, you will authorize your users to increase/complete the class' interface.
从另一方面看,这在设计代码时很重要,因为通过将函数放在命名空间中,您将授权用户增加/完成类的接口。
Extension II
扩展二
A side-effect of the previous point, it is impossible to declare static methods in multiple headers. Every method must be declared in the same class.
上一点的副作用是,不可能在多个标头中声明静态方法。每个方法都必须在同一个类中声明。
For namespaces, functions from the same namespace can be declared in multiple headers (the almost-standard swap function is the best example of that).
对于命名空间,来自同一命名空间的函数可以在多个头文件中声明(几乎标准的交换函数是最好的例子)。
Extension III
扩展三
The basic coolness of a namespace is that in some code, you can avoid mentioning it, if you use the keyword "using":
命名空间的基本优势在于,在某些代码中,如果使用关键字“using”,则可以避免提及它:
#include <string>
#include <vector>
// Etc.
{
using namespace std ;
// Now, everything from std is accessible without qualification
string s ; // Ok
vector v ; // Ok
}
string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR
And you can even limit the "pollution" to one class:
您甚至可以将“污染”限制为一类:
#include <string>
#include <vector>
{
using std::string ;
string s ; // Ok
vector v ; // COMPILATION ERROR
}
string ss ; // COMPILATION ERROR
vector vv ; // COMPILATION ERROR
This "pattern" is mandatory for the proper use of the almost-standard swap idiom.
这种“模式”对于正确使用几乎标准的交换习语是强制性的。
And this is impossible to do with static methods in classes.
这对于类中的静态方法是不可能的。
So, C++ namespaces have their own semantics.
所以,C++ 命名空间有自己的语义。
But it goes further, as you can combine namespaces in a way similar to inheritance.
但它更进一步,因为您可以以类似于继承的方式组合命名空间。
For example, if you have a namespace A with a function AAA, a namespace B with a function BBB, you can declare a namespace C, and bring AAA and BBB in this namespace with the keyword using.
例如,如果您有一个命名空间 A 带有函数 AAA,一个命名空间 B 带有函数 BBB,您可以声明一个命名空间 C,并使用关键字 using 将 AAA 和 BBB 带入该命名空间。
Conclusion
结论
Namespaces are for namespaces. Classes are for classes.
命名空间用于命名空间。班级是为了班级。
C++ was designed so each concept is different, and is used differently, in different cases, as a solution to different problems.
C++ 被设计成每个概念都是不同的,并且在不同的情况下以不同的方式使用,作为不同问题的解决方案。
Don't use classes when you need namespaces.
需要命名空间时不要使用类。
And in your case, you need namespaces.
在您的情况下,您需要命名空间。
回答by Dan Tao
There are a lot of people who would disagree with me, but this is how I see it:
有很多人不同意我的观点,但我是这样看待它的:
A class is essentially a definition of a certain kind of object. Static methods should define operations that are intimately tied to that object definition.
类本质上是某种对象的定义。静态方法应该定义与该对象定义密切相关的操作。
If you are just going to have a group of related functions not associated with an underlying object or definition of a kind of object, then I would say go with a namespace only. Just for me, conceptually, this is a lot more sensible.
如果您只想拥有一组与底层对象或某种对象的定义无关的相关函数,那么我会说只使用命名空间。就我而言,从概念上讲,这更明智。
For instance, in your case, ask yourself, "What is a MyMath?" If MyMath
does not define a kind of object, then Iwould say: don't make it a class.
例如,在您的情况下,问问自己,“什么是 MyMath?” 如果MyMath
没有定义一种对象,那么我会说:不要让它成为一个类。
But like I said, I know there are plenty of folks who would (even vehemently) disagree with me on this (in particular, Java and C# developers).
但就像我说的,我知道有很多人会(甚至强烈地)不同意我的观点(特别是 Java 和 C# 开发人员)。
回答by Shog9
- If you need static data, use static methods.
- If they're template functions and you'd like to be able to specify a set of template parameters for all functions together then use static methods in a template class.
- 如果需要静态数据,请使用静态方法。
- 如果它们是模板函数,并且您希望能够为所有函数一起指定一组模板参数,那么请在模板类中使用静态方法。
Otherwise, use namespaced functions.
否则,使用命名空间函数。
In response to the comments: yes, static methods and static data tend to be over-used. That's why I offered only two, relatedscenarios where I think they can be helpful. In the OP's specific example (a set of math routines), if he wanted the ability to specify parameters - say, a core data type and output precision - that would be applied to all routines, he might do something like:
回应评论:是的,静态方法和静态数据往往被过度使用。这就是为什么我只提供了两个相关的场景,我认为它们会有所帮助。在 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;
If you don't need that, then by all meansuse a namespace.
如果您不需要它,那么一定要使用命名空间。
回答by coppro
You should use a namespace, because a namespace has the many advantages over a class:
你应该使用命名空间,因为命名空间比类有很多优点:
- You don't have to define everything in the same header
- You don't need to expose all your implementation in the header
- You can't
using
a class member; you canusing
a namespace member - You can't
using class
, thoughusing namespace
is not all that often a good idea - Using a class implies that there is some object to be created when there really is none
- 您不必在同一个标题中定义所有内容
- 您不需要在标头中公开所有实现
- 你不能
using
是班级成员;你可以using
是命名空间成员 - 你不能
using class
,虽然using namespace
这通常不是一个好主意 - 使用类意味着当确实没有对象时,会创建一些对象
Static members are, in my opinion, very very overused. They aren't a real necessity in most cases. Static members functions are probably better off as file-scope functions, and static data members are just global objects with a better, undeserved reputation.
在我看来,静态成员被过度使用了。在大多数情况下,它们并不是真正的必需品。静态成员函数可能更适合作为文件范围函数,而静态数据成员只是具有更好的、不应有的声誉的全局对象。
回答by Motti
I would prefer namespaces, that way you can have private data in an anonymous namespace in the implementation file (so it doesn't have to show up in the header at all as opposed to private
members). Another benefit is that by using
your namespace the clients of the methods can opt out of specifying MyMath::
我更喜欢命名空间,这样你就可以在实现文件的匿名命名空间中拥有私有数据(所以它根本不必显示在标题中,而不是private
成员)。另一个好处是,通过using
您的命名空间,方法的客户端可以选择不指定MyMath::
回答by Milind T
One more reason to use class - Option to make use of access specifiers. You can then possibly break your public static method into smaller private methods. Public method can call multiple private methods.
使用类的另一个原因 - 使用访问说明符的选项。然后,您可以将公共静态方法分解为更小的私有方法。公共方法可以调用多个私有方法。
回答by rocd
Both namespace and class method have their uses. Namespace have the ability to be spread across files however that is a weakness if you need to enforce all related code to go in one file. As mentioned above class also allows you to create private static members in the class. You can have it in the anonymous namespace of the implementation file however it is still a bigger scope than having them inside the class.
命名空间和类方法都有它们的用途。命名空间具有跨文件分布的能力,但是如果您需要强制所有相关代码进入一个文件,这是一个弱点。如上所述,类还允许您在类中创建私有静态成员。您可以将它放在实现文件的匿名命名空间中,但是它仍然比将它们放在类中的范围更大。