C++ 静态与常量成员函数

C++ 静态与常量成员函数,c++,C++,我发现很难决定何时使用私有静态成员函数以及何时使用私有常量成员函数 假设我们有一个DoSomething()方法,它需要检查一个或多个成员是否是某个对象: class Foo { public: void DoSomething() { // if(IsASomething()) ... // or // if(IsSomething(a_)) ... private: int* a_; int* b_;

我发现很难决定何时使用私有静态成员函数以及何时使用私有常量成员函数

假设我们有一个DoSomething()方法,它需要检查一个或多个成员是否是某个对象:

class Foo
{
public:
    void DoSomething()
    {
         // if(IsASomething()) ...
         // or
         // if(IsSomething(a_)) ...
private:

    int* a_;
    int* b_;

    static bool IsSomething(int* n) {return n != null;}

    bool IsASomething() const { return a_ != null;}
    bool IsBSomething() const{ return b_ != null;}
};
当一个helper函数只以一种方式使用时(比如只检查a_u是否有意义),我倾向于使用const成员函数。如果它将与几个参数一起使用,我倾向于使用静态版本。有没有其他我没有想到的因素会说服我做出不同的选择

编辑:我想我解释得不好,所以我在示例中添加了定义。

  • 静态
    函数不能使用任何非静态成员函数或变量

  • 静态
    函数不能以多态方式重写

  • 您可以获取
    静态
    函数的地址

  • 调用
    静态
    函数不需要类的实例

  • 标记为
    const
    的成员函数可以访问类成员,调用其他
    const
    函数,如果标记为
    virtual
    ,则可以进行多态重写


  • 函数后的
    const
    表示“此函数不修改任何类成员[标记为
    mutable
    ]的除外]

    static
    表示“此函数没有传递给函数的隐藏的
    this
    指针”,因此它实际上与任何不属于类的自由函数一样,只是它在类内部有一种“名称空间”

    他们是完全不同的“动物”

    编辑:这实际上取决于什么对类/系统设计最有意义。对于实际上不属于类的东西,通常使用
    静态
    函数是正确的。我很少使用
    静态
    函数,因为它们除了在一些非常特殊的情况下没有什么意义-这里要问的问题是“如果我把它设为静态的,为什么它是这个类的一部分?”,如果答案是“因为它属于它所属的类”,那么它应该是一个
    静态的
    函数。另一方面,如果答案不是一个实实在在的原因,那么它可能不属于这个类,并且应该以无静态函数结束(可能在一个不规则的命名空间中)在源文件中,而不是在类中

    在我的编译器项目中(总共有13000行C++代码),我有:

    • 一个
      静态
      成员函数(将字符串转换为令牌类中的关键字令牌-因为它是在令牌本身的构造过程中调用的,因此不适合作为成员函数)
    • 非成员函数的.cpp文件中大约有50个
      静态
      函数。这些函数的作用如下:
      
      • IsConstant()
        用于某些表达式
        • 不,我不希望它作为表达式本身的成员函数,因为它是一个可以表达很多东西的泛型类,这意味着我必须有几十个
          返回false
          虚拟函数的实现,这是一种相对罕见的情况]
      • 错误函数(打印错误消息)
      • 可以使它们成为静态成员,但类的用户不需要使用这些函数,这意味着将它们公开给外部是毫无意义的

    如果可能,我倾向于在未命名的命名空间中使用自由函数

    所以

    // header
    
    class A
    {
    public:
        bool HasCustomProperty() const();
    private:
        bool IsOdd() const;
        bool IsHappy() const;
    private:
        int a;
    };
    
    // cpp
    
    bool A::HasCustomProperty() const
    {
        return IsOdd() && IsHappy();
    }
    


    我选择最后一个。

    它们是两个不同的东西,不是交替的:

    const成员函数不允许修改类即时数据。 静态成员函数没有关联的类实例

    使用OP的示例类定义,然后在inplementstion中

    bool Foo::IsSomething(int* n)
    {
       return *n < *a_; // not ok. static method has no this    
    }
    
    
    bool Foo::IsASomething() const
    {
       return (*a_ > 8) // ok as member a_ not changed
    }
    
    bool Foo::IsASomething() const
    {
        *a_ +=4;   // not ok as a_ cannot be changed by const member
        return (*a_ > 8);
    }
    
    bool-Foo::IsSomething(int*n)
    {
    return*n<*a;//不正常。静态方法没有此属性
    }
    bool Foo::IsASomething()常量
    {
    return(*a\u>8)//作为成员a\u8确定未更改
    }
    bool Foo::IsASomething()常量
    {
    *a_+=4;//不正常,因为常量成员无法更改a
    返回(*a>8);
    }
    
    为什么还要让它们成为成员函数呢?如果它们是
    私有的
    ,很有可能您可以将它们从类中提升出来,并在cpp文件中的未命名命名空间内执行函数签入。有趣的阅读:您当然不会混淆它们,因为它们之间没有关联。您必须阅读一些标准文本这。@JonnyHenly@harpribot:OP想知道在(示例)
    c.begin()
    vs
    begin(c)
    (但对于私有内容)之间选择哪一种。@JonnyHenly:@Jaciq:您可以调用
    Foo::IsSomething(nullptr);
    ,因此没有实例。@Jarod42不要求函数是公共的吗?@Jaciq:可能是朋友的调用,来自
    Foo
    内部创建的lambda(实例与否)。(顺便说一句,从您的第一句话中不清楚它与可见性有关)@Jarod42我没有考虑过lambda,我想可能会发生一个关于friend的案例,尽管我个人认为这是一个糟糕的设计。是的,我可以把评论写得更清楚。答案似乎是没有区分公共静态方法和私有静态方法。OP想知道在(示例)
    c.begin()中选择哪一个
    vs
    begin(c)
    (但私人物品除外)。我想我可能对这个问题的措辞很糟糕。我理解常量和静态成员函数之间的区别,我只是指出它们可以以非常相似的方式使用,我发现很难选择。我编辑了一些内容,添加了一些关于何时使用的信息。我理解常量成员函数是不允许的修改数据成员和该静态成员函数
    // header
    
    class A
    {
    public:
        bool HasCustomProperty() const();
    private:
        int a;
    };
    
    // cpp
    namespace {
        bool IsOdd(int n);
        bool IsHappy(int n);
    }
    
    bool A::HasCustomProperty() const
    {
        return IsOdd(a) && IsHappy(a);
    }
    
    bool Foo::IsSomething(int* n)
    {
       return *n < *a_; // not ok. static method has no this    
    }
    
    
    bool Foo::IsASomething() const
    {
       return (*a_ > 8) // ok as member a_ not changed
    }
    
    bool Foo::IsASomething() const
    {
        *a_ +=4;   // not ok as a_ cannot be changed by const member
        return (*a_ > 8);
    }