命名空间+函数与类上的静态方法 [英] Namespace + functions versus static methods on a class

查看:140
本文介绍了命名空间+函数与类上的静态方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说,我有或者将要写一组相关的函数。让我们说他们是数学相关的。在组织上,我应该:


  1. 编写这些函数并将它们放在我的 MyMath 命名空间并通过 MyMath :: XYZ()

  2. 创建一个名为 MyMath 并使这些方法静态,并引用类似 MyMath :: XYZ()

为什么要选择一个作为组织我的软件的方法?

解决方案

默认情况下,使用命名空间函数。



类是构建对象而不是替换命名空间。



面向对象代码



Scott Meyers为他的有效C ++书写了一个关于这个主题的整数项,喜欢非成员非朋友函数到成员函数。我在Herb Sutter的文章中找到了这个原则的在线参考: http://www.gotw.ca/gotw/084.htm



重要的是要知道:在同一命名空间中的C ++函数属于该类的接口(因为 ADL 将在解析函数调用时搜索这些函数。



命名空间函数,除非声明friend不能访问类的内部,而静态方法有。



这意味着,例如,当维护你的类时,如果你需要改变



扩展I



在类的接口中添加代码。



在C#中,即使没有访问权限,也可以向类中添加方法。但是在C ++中,这是不可能的。



但是,仍然在C ++中,你仍然可以添加一个命名空间函数,甚至是一个人为你写的类。

另一方面,这在设计代码时很重要,因为通过将你的函数放在命名空间中,你将授权你的用户增加/完成类的接口。 p>

扩展II



上一点的副作用,不可能在多个标题中声明静态方法。每个方法必须在同一个类中声明。



对于命名空间,来自同一命名空间的函数可以在多个头文件中声明(几乎标准的交换函数是最好的例子



扩展III



命名空间的基本功能是在某些代码中,如果您使用关键字using,请避免提及它:

  #include< string& 
#include< vector>

//等等。
{
using namespace std;
//现在,std中的所有内容都是可访问的,不需要验证
string s; // Ok
vector v; // Ok
}

string ss; // COMPILATION ERROR
vector vv; // COMPILATION ERROR

您甚至可以将污染限制为一个类别:

  #include< string> 
#include< vector>

{
使用std :: string;
string s; // Ok
vector v; // COMPILATION ERROR
}

string ss; // COMPILATION ERROR
vector vv; // COMPILATION ERROR

这种模式是正确使用几乎标准的交换习语所必需的。



这是不可能在类中使用静态方法。



因此,C ++命名空间有自己的语义。



但更进一步,你可以以类似继承的方式组合命名空间。



,如果你有一个命名空间A,一个函数AAA,一个命名空间B,函数BBB,你可以声明一个命名空间C,并带有关键字使用的命名空间中的AAA和BBB。



结论



命名空间用于命名空间。
类用于类。



C ++的设计使每个概念都不同,在不同的情况下,它们被用于不同的问题的解决方案。 p>

当你需要命名空间时,不要使用类。



在你的情况下,你需要命名空间。 >

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:

  1. Write these functions and put them in my MyMath namespace and refer to them via MyMath::XYZ()
  2. Create a class called MyMath and make these methods static and refer to the similarly MyMath::XYZ()

Why would I choose one over the other as a means of organizing my software?

解决方案

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

The important thing to know is that: In C++ functions in the same namespace as a class belong to that class' interface (because ADL will search those functions when resolving function calls).

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.

But, still in C++, you can still add a namespaced function, even to a class someone wrote for you.

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 methods 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 cooless of a namespace is that in some code, you can avoid mentioning it, if you use the keyword "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 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.

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.

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 solution to different problems.

Don't use classes when you need namespaces.

And in your case, you need namespaces.

这篇关于命名空间+函数与类上的静态方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆