54

boost::asio の例のリクエスト パーサーを見ていましたが、なぜプライベート メンバー関数is_char()static? :

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

静的関数ではない関数consumerで使用されます。

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

この関数は、内部で動作するクラスのオブジェクトを必要としないため、簡単に独立させることができます。関数をフリー関数ではなくクラスの静的メンバーにすることには、2 つの利点があります。

  1. オブジェクトが静的であるか、関数に渡される場合、クラスの任意のオブジェクトのプライベートおよび保護されたメンバーへのアクセスを関数に与えます。
  2. 名前空間と同様の方法で関数をクラスに関連付けます。

この場合、2 番目のポイントのみが適用されるようです。

于 2011-06-22T20:18:27.900 に答える
23

これらの関数が静的である理由はありますか?

staticメンバー関数には、 という非表示の追加パラメーターがありますthis。これを渡すのは無料ではないため、private関数を作成することは最適化staticの手段と見なすことができます。 ただし、コードで要件/設計を表現する手段と見なすこともできます。その関数がクラスのメンバーデータを参照する必要がない場合、なぜそれを非メンバー関数にする必要があるのでしょうか?
static

ただし、メンバー関数の型を変更するpublicprivatestaticまたは変更しない場合は、すべてのクライアントを再コンパイルする必要があります。privateそれらのクライアントが決して使用できない機能のためにこれを行う必要がある場合、それはリソースの無駄です。したがって、私は通常、できるだけ多くの関数をクラスのプライベート パーツから実装ファイルの名前のない名前空間に移動します。

于 2011-06-22T20:14:45.263 に答える
8

この特定の例では、 a の選択static is_char()はおそらくドキュメントのものです。その意図は、is_char()メソッドがクラスの特定のインスタンスに限定されていないことを印象づけることですが、機能はクラス自体に固有のものです。

言い換えれば、それを作ることによって、static彼らはそれがある種の効用関数であると言っているis_char()のです...特定のインスタンスの状態に関係なく使用できるものです。それを作成することによりprivate、彼らはあなたが(クライアントとして)それを使用しようとすべきではないと言っています. それはあなたが思っていることをしないか、非常に制約され、制御された方法で実装されています。

@Mark Ransom の回答は、プライベートな静的メンバー関数を実際に使用するための良い点をもたらします。具体的には、そのメンバー関数は、静的オブジェクトまたはインスタンス化されたオブジェクトの渡されたインスタンスのいずれかのプライベートおよび保護されたメンバーにアクセスできます。

これの一般的なアプリケーションの 1 つは、オブジェクト指向の方法で 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 に答える