web-dev-qa-db-ja.com

プライベート静的メンバー関数の使用とは何ですか?

Boost :: asioの例の request parser を見ていましたが、なぜis_char()のようなプライベートメンバー関数がstatic?なのか疑問に思っていました。 :

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

関数で使用されます consume これは静的関数ではありません:

_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()を呼び出していません。これらの関数が静的である理由はありますか?

40
rve

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

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

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

65
Mark Ransom

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

static以外のメンバー関数には、thisと呼ばれる非表示の追加パラメーターがあります。これを渡すことは無料ではありません。そのため、private関数staticを作成することは、optimizationの手段として見ることができます。
しかし、それはあなたのコードであなたの要件/設計を表現する手段として見ることもできます:その関数はクラスのメンバーデータを参照する必要はありませんが、なぜそれが非staticメンバー関数である必要がありますか?

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

16
sbi

この特定の例では、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();
}
...
5
dolphy

request_parserオブジェクトのメンバー変数にアクセスする必要がないため、静的です。したがって、関数がアクセスできる状態の量を減らすため、静的にすると関数が分離されます。

価値があるのは、この関数がrequest_parserクラスの一部でなかった場合、さらに優れていたはずです。代わりに、.cppファイル内の(おそらく名前空間内の)無料の関数でなければなりませんでした。

2
Frerich Raabe

ポイントはwhereではありません。問題はwhatが使用することです。その定義が非静的メンバーを使用しない場合、冗長なパラメーターを関数に渡さないという同じ原則に従って、関数を静的にします(オーバーロードの結果で使用される場合を除く)

0
Armen Tsirunyan