私有静态成员函数有什么用?

rve*_*rve 42 c++ static-methods private-members

我一直在寻找的请求剖析从升压:: ASIO例子,我想知道为什么私有成员函数一样is_char()static?:

class request_parser
{
  ...
  private:
    static bool is_char(int c);
  ...
};
Run Code Online (Sandbox Code Playgroud)

它用在函数消耗中,它不是静态函数:

boost::tribool request_parser::consume(request& req, char input)
{
  switch (state_)
  {
    case method_start:
    if (!is_char(input) || is_ctl(input) || is_tspecial(input))
    {
      return false;
    }
    ...
Run Code Online (Sandbox Code Playgroud)

只有成员函数可以调用,is_char()并且没有静态成员函数正在调用is_char().那么为什么这些函数是静态的呢?

Mar*_*som 68

这个功能可以很容易地独立,因为它不需要类的对象在其中操作.使函数成为类的静态成员而不是自由函数有两个优点:

  1. 如果对象是静态的或传递给函数,它允许函数访问类的任何对象的私有成员和受保护成员;
  2. 它以与命名空间类似的方式将函数与类相关联.

在这种情况下,似乎只有第二点适用.

  • 对于数字1 +1,这经常被忽视 (7认同)
  • @Oli:是的,您基本上在参数中明确了“this”指针。 (2认同)
  • +1 第一个子弹,我忘记了。一个补充 - 它还允许函数访问类本身的私有和受保护成员(阅读:具有私有或受保护可见性的静态变量)。 (2认同)

sbi*_*sbi 17

那么为什么这些函数是静态的呢?

static成员函数有一个隐藏的附加参数调用this.传递这个并不是免费的,所以制作一个private功能static可以看作是一种优化手段.
但它也可以看作是在代码表达您的需求/设计的一种方法:如果该函数不需要引用该类的任何成员数据,为什么它应该是非static成员函数?

但是,改变任何成员函数的类型,public或者private,static还是不行,将要求所有的客户重新编译.如果需要为private这些客户端永远不能使用的功能执行此操作,则会浪费资源.因此,我通常将尽可能多的函数从类的私有部分移动到实现文件中未命名命名空间中.


dol*_*phy 5

对于此特定示例,a的选择static is_char()很可能是文档。目的是使您印象深刻的是,该is_char()方法并不局限于该类的特定实例,而是该功能是特定于该类本身的

换句话说,static他们说这is_char()是一种效用函数……不管给定实例的状态如何,都可以使用它。通过这样做private,他们说您(作为客户)不应尝试使用它。它要么不执行您认为的操作,要么以非常受约束的受控方式实现。

@Mark Ransom的答案为私有静态成员函数的实际使用提出了一个很好的观点。具体来说,该成员函数可以访问静态对象或实例化对象的传递实例的私有成员和受保护成员。

这种方法的一个常见应用是以某种面向对象的方式抽象pthread实现。您的线程函数必须是静态的,但将其声明为私有将限制该函数对类的访问(除了最确定的之外)。线程可以被传递给正在“隐藏”的类的实例,现在可以使用对象的成员数据执行逻辑。

简单的例子:

[MyWorkerClass.h]
...
public:
    bool createThread();

private:
    int getThisObjectsData();

    pthread_t    myThreadId_;
    static void* myThread( void *arg );
...

[MyWorkerClass.cpp]
...
bool MyWorkerClass::createThread()
{
    ...
    int result =  pthread_create(myThreadId_, 
                                 NULL,
                                 myThread), 
                                 this);
    ...
}

/*static*/ void* MyWorkerClass::myThread( void *arg )
{
    MyWorkerClass* thisObj = (MyWorkerClass*)(arg);
    int someData = thisObj->getThisObjectsData();
}
...
Run Code Online (Sandbox Code Playgroud)