假设我有或将要编写一组相关函数。假设它们与数学有关。在组织上,我应该:
MyMath
命名空间并通过 MyMath::XYZ()
引用它们MyMath
的类并将这些方法设为静态并引用类似的 MyMath::XYZ()
为什么我会选择其中一个来组织我的软件?
最佳答案
默认情况下,使用命名空间函数。
类是构建对象,而不是替换命名空间。
在面向对象的代码中
Scott Meyers 为他的 Effective C++ 书写了一整篇关于这个主题的文章,“Prefer non-member non-friend functions to member functions”。我在 Herb Sutter 的一篇文章中找到了对这一原则的在线引用:http://www.gotw.ca/gotw/084.htm
需要知道的重要一点是:在 C++ 中,与类在同一命名空间中并且以该类为参数的函数属于该类的接口(interface)(因为 ADL 将在解析函数时搜索这些函数来电)。
For example:
- let's say you have a namespace N
- let's say you have a class C, declared in namespace N (in other words, its full name is N::C)
- let's say you have a function F, declared in namespace N (in other words, its full name is N::F)
- let's say that function F has, among its parameters, a parameter of type C
... Then N::F is part of N::C's public interface.
命名空间函数,除非声明为“ friend ”,否则无法访问类的内部,而静态方法有权访问类的内部。
这意味着,例如,在维护您的类时,如果您需要更改类的内部结构,您将需要在其所有方法中搜索副作用,包括静态方法。
扩展一
将代码添加到类的接口(interface)。
在 C# 中,即使您无权访问,也可以向类添加方法。但在 C++ 中,这是不可能的。
但是,仍然在 C++ 中,您仍然可以添加命名空间函数,甚至可以添加到某人为您编写的类中。
从另一方面来看,这在设计代码时很重要,因为通过将函数放在命名空间中,您将授权您的用户增加/完成类的接口(interface)。
扩展二
前一点的副作用是,不可能在多个头文件中声明静态方法。每个方法都必须在同一个类中声明。
对于命名空间,来自同一个命名空间的函数可以在多个头文件中声明(几乎标准的交换函数就是最好的例子)。
扩展三
命名空间的基本酷点在于,在某些代码中,您可以避免提及它,如果您使用关键字
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
您甚至可以将“污染”限制为一类:#include <string>
#include <vector>
{
using 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
在此命名空间中,使用关键字 using
.您甚至可以使用
using namespace
将一个 namespace 的全部内容带入另一个 namespace 。 ,如命名空间 D!namespace A
{
void AAA();
void AAA2();
}
namespace B
{
void BBB();
}
namespace C
{
using A::AAA;
using B::BBB;
}
namespace D
{
using namespace A;
using namespace B;
}
void foo()
{
C::AAA();
// C::AAA2(); // ERROR, won't compile
C::BBB();
}
void bar()
{
D::AAA();
D::AAA2();
D::BBB();
}
结论命名空间用于命名空间。
类是为了类。
C++ 的设计使每个概念都是不同的,并且在不同的情况下以不同的方式使用,作为不同问题的解决方案。
当你需要命名空间时不要使用类。
在您的情况下,您需要命名空间。
关于c++ - 命名空间 + 函数与类上的静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61288800/