c++ - 命名空间 + 函数与类上的静态方法

标签 c++ namespaces static-methods

假设我有或将要编写一组相关的函数。假设它们与数学有关。在组织上,我应该:

  1. 编写这些函数并将它们放在我的 MyMath 命名空间中,并通过 MyMath::XYZ()
  2. 引用它们
  3. 创建一个名为 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 ”,否则无法访问类的内部,而静态方法有权访问类的内部。

这意味着,例如,在维护类时,如果您需要更改类的内部结构,则需要在其所有方法中搜索副作用,包括静态方法。

扩展 I

向类的接口(interface)添加代码。

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

但是,仍然在 C++ 中,您仍然可以添加命名空间函数,甚至可以添加到有人为您编写的类中。

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

扩展 II

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

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

扩展 III

命名空间最酷的地方在于,在某些代码中,你可以避免提及它,如果你使用关键字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,并在这个命名空间中引入AAABBB关键字using .

您甚至可以使用 using 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/1434937/

相关文章:

c++ - Windows 上 emacs 中的 Company-clang 模式

c++ - 基于模板参数的模板化类强制参数数量

C#:从基类静态方法确定派生对象类型

java - Java中静态方法不支持动态多态的原因

c++ - 在无效对象上调用成员函数

c# - 显示模态对话框时淡化背景

c++ - 在命名空间中声明变量,在 main 中定义它,使其对所有其他文件可见

c++ - 命名空间范围内的外部 - gcc vs clang vs msvc

xml - xsd 架构引用和类型属性值的命名空间如何别名/绑定(bind)?

javascript - 在javascript中使用子类中的静态方法