Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 名称空间+;函数与类上的静态方法_C++_Namespaces_Static Methods - Fatal编程技术网

C++ 名称空间+;函数与类上的静态方法

C++ 名称空间+;函数与类上的静态方法,c++,namespaces,static-methods,C++,Namespaces,Static Methods,假设我有,或将要写,一组相关函数。假设它们与数学有关。在组织上,我应该: 编写这些函数并将它们放在myMyMath命名空间中,并通过MyMath::XYZ()引用它们 创建一个名为MyMath的类,将这些方法设置为静态,并引用类似的MyMath::XYZ() 为什么我会选择其中一种方式来组织我的软件? 如果需要静态数据,请使用静态方法 如果它们是模板函数,并且您希望能够同时为所有函数指定一组模板参数,那么在模板类中使用静态方法 否则,请使用命名空间函数 回应评论:是的,静态方法和静态数据往往

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

  • 编写这些函数并将它们放在my
    MyMath
    命名空间中,并通过
    MyMath::XYZ()引用它们
  • 创建一个名为
    MyMath
    的类,将这些方法设置为静态,并引用类似的
    MyMath::XYZ()
  • 为什么我会选择其中一种方式来组织我的软件?

    • 如果需要静态数据,请使用静态方法
    • 如果它们是模板函数,并且您希望能够同时为所有函数指定一组模板参数,那么在模板类中使用静态方法
    否则,请使用命名空间函数


    回应评论:是的,静态方法和静态数据往往被过度使用。这就是为什么我只提供了两个相关的场景,我认为它们会有所帮助。在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;
    
    模板
    我的数学课
    {
    //例程对数据类型T进行操作,至少保留小数位数精度
    };
    //用于制造计算的数学例程
    typedef MyMath-CAMMath;
    //屏幕显示的数学例程
    typedef MyMath预览路径;
    

    如果你不需要,那就尽量使用名称空间。

    有很多人不同意我的观点,但我是这么看的:

    类本质上是某种对象的定义。静态方法应该定义与该对象定义密切相关的操作

    如果您只需要一组相关函数,而这些函数与底层对象或某类对象的定义没有关联,那么我会说只使用名称空间。就我而言,从概念上来说,这更合理

    例如,在你的例子中,问你自己,“什么是MyMath?”如果
    MyMath
    没有定义一种对象,那么我会说:不要把它变成类


    但正如我所说,我知道有很多人(甚至强烈地)不同意我的观点(特别是Java和C#开发者)。

    我更喜欢名称空间,这样你就可以在实现文件中的匿名名称空间中拥有私有数据(因此,与
    private
    成员相比,它根本不必显示在标题中)。另一个好处是,通过
    使用
    您的命名空间,方法的客户端可以选择不指定
    MyMath::

    您应该使用命名空间,因为命名空间比类有许多优点:

    • 您不必在同一个标题中定义所有内容

    • 您不需要在报头中公开所有实现
    • 不能使用类成员
      ;可以使用命名空间成员
    • 您不能
      使用类
      ,尽管
      使用名称空间
      通常不是一个好主意
    • 使用类意味着在实际上没有对象的情况下要创建一些对象
    在我看来,静态成员被过度使用了。在大多数情况下,它们不是真正必要的。静态成员函数作为文件作用域函数可能更好,而静态数据成员只是具有更好、不应有声誉的全局对象。

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

    类用于构建对象,而不是替换名称空间

    在面向对象代码中 Scott Meyers为他的有效C++书写了一个完整的条目:“更喜欢非成员非朋友的函数到成员函数”。我在Habor萨特的一篇文章中找到了这个原则的在线参考:< /P>

    重要的是要知道:在C++中,与类相同的命名空间中的函数是作为参数的类,属于该类的接口(因为在解析函数调用时将搜索这些函数)。 例如:

    • 假设您有一个名称空间N
    • 假设您有一个类C,在命名空间N中声明(换句话说,它的全名是N::C
    • 假设您有一个函数F,在命名空间N中声明(换句话说,它的全名是N::F
    • 假设函数F的参数中有一个C
    …那么N::F就是N::C公共界面的一部分

    命名空间函数,除非声明为“friend”,否则不能访问类的内部,而静态方法可以访问

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

    扩展一 向类的接口添加代码

    中,你可以添加方法到一个类,即使你没有访问它。但是在C++中,这是不可能的。

    但是,在C++中,你仍然可以添加一个名字空间函数,即使是某人为你编写的类。 从另一方面看,这在设计代码时很重要,因为通过将函数放在命名空间中,您将授权用户增加/完成类的接口

    扩展II 前一点的一个副作用是,不可能在多个头中声明静态方法。每个方法都必须在同一个类中声明

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

    扩展III 名称空间的基本特点是,在某些代码中,如果使用关键字#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
    
    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();
    }