54

我正在查看 boost::asio 示例中的请求解析器,我想知道为什么私有成员函数是这样is_char()static?:

class request_parser
{
  ...
  private:
    static bool is_char(int c);
  ...
};

它用于不是静态函数的函数消费者:

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

只有成员函数可以调用is_char(),没有静态成员函数在调用is_char()。那么这些函数是静态的有什么原因吗?

4

5 回答 5

82

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

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

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

于 2011-06-22T20:18:27.900 回答
23

那么这些函数是静态的有什么原因吗?

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

但是,更改任何成员函数的类型,orpublic或不,将需要所有客户端重新编译。如果需要为那些客户永远无法使用的功能完成此操作,那是一种资源浪费。因此,我通常将尽可能多的函数从类的私有部分移动到实现文件中的未命名命名空间中privatestaticprivate

于 2011-06-22T20:14:45.263 回答
8

对于这个特定示例,选择 astatic 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();
}
...
于 2011-06-22T20:54:32.077 回答
3

它是静态的,因为它不需要访问request_parser对象的任何成员变量。因此,将其设为静态会使函数解耦,因为它减少了函数可以访问的状态量。

对于它的价值,如果这个函数根本不是类的一部分会更好request_parser- 相反,它应该是(可能在命名空间中).cpp文件中的一个自由函数。

于 2011-06-22T20:14:34.060 回答
1

重点不在于使用它的地方。问题是它使用什么。如果它的定义不使用任何非静态成员,我会将函数设为静态,根据我不会将冗余参数传递给任何函数的相同原则(除非它们用于重载结果)

于 2011-06-22T20:15:41.737 回答