静态与const成员函数



我发现很难决定什么时候使用私有静态成员函数,什么时候使用私有const成员函数。

假设我们有一个方法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;}
};

当辅助函数只以一种方式使用时(比如只检查a_是否为某物),我倾向于使用const成员函数。如果它将与几个参数一起使用,我倾向于坚持使用静态版本。还有其他我没有想到的因素会说服我做出不同的选择吗?

编辑:我认为我解释得不好,所以我在例子中添加了定义

在可能的情况下,我倾向于在未命名的命名空间中使用自由函数。

之间
// 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();
}

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

// 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);
}
  1. static函数不能使用任何非静态成员函数或变量。

  2. static函数不能被多态覆盖

  3. static函数的地址

  4. 你不需要一个类的实例来调用static函数

  5. 标记为const的成员函数可以访问类成员,调用其他const函数,如果标记为virtual被多态覆盖。

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

static意味着"该函数没有一个隐藏的this指针传递给该函数",所以它实际上就像任何不属于类的自由函数一样,只是它有点像"命名空间"。

它们是完全不同的"动物"。

编辑:这真的要归结为什么对职业/系统设计最有意义。对于实际上不属于类的东西,使用static函数通常是正确的。我很少使用static函数,因为它们除了在一些非常特殊的情况下没有什么意义——这里要问的问题是,"如果我把它设为静态,为什么它是这个类的一部分?"如果答案是"因为它属于这个类",那么它应该是一个static函数。另一方面,如果答案不是一个可靠的理由,那么它可能不属于类,并且应该在源文件中作为静态自由函数(可能在匿名命名空间中)结束,而不是在类中。

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

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

它们是两个不同的东西,不能相互替换:

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

使用OP的示例类定义,然后在实现…

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);
}

最新更新