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

标签 c++ namespaces static-methods

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

  • 把这些函数写出来放在我的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 ,并带上AAABBB在此命名空间中,使用关键字 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/

    相关文章:

    c++ - 模板参数替换失败,并且未完成隐式转换

    python - 与自定义库 Python 中名为 tensorflow 的包冲突

    c# - 使用单一方法类——最好的方法?

    c++ - 将 C++ 项目导入到 Eclipse - 重叠工作区

    c++ - 有谁知道在线免费的 C++ 评估测试?

    c++ - 使用gcc或cpp搜索定义的位置

    c++ - 在 `foo` 的定义中使用 `bar::foo` ?

    PHP 命名空间和实现关键字

    c++ - 返回静态变量时static const和static的区别

    Java对子类的静态反射