2011-02-07 13 views
10

重複の可能性:
Where would you use a friend function vs a static function?
C++: static member functions静的メンバー関数を使用する場合

それはC++の静的メンバ関数を使用するのが適切でしょうか?私に実世界の例を教えてください。

+2

「oops」タグは何ですか? – Maxpm

+2

私は著者が「OOP」つまりオブジェクト指向プログラミングを意味すると思って質問を編集しました。 –

+1

http://stackoverflow.com/questions/4723143/c-static-member-functions – Mahesh

答えて

11

良い用途:

  • メタプログラミング。実際の例はテンプレートstd :: char_traitsです。すべてのメンバ関数は静的です
  • これを静的メンバ関数にすると、クラスのプライベートメンバにアクセスできるようになりますが、フレンドもここで十分です。
  • したがって、静的メンバ関数は、それ。

最後のケースは、保護された静的メンバー関数に適用されますが、非公開のものではありません。後者の場合は、クラスのコンパイル単位に入れるだけで、実装の詳細として隠すことができます。制限された方法ではあるものの、保護されたものは表示したいと思っていますが。

その典型的な例は、友情の継承の欠如を「欺く」ことです。

class B 
{ 
    friend class A; 
    // lots of private stuff 
}; 

class A 
{ 
protected: 
    static void callsSomePrivateMembers(B& b); 
}; 

class AChild : public A 
{ 
    void foo(B& b); 
} 

void AChild::foo(B& b) 
{ 
     // AChild does not have private access to B as friendship is not inherited 
     // but I do have access to protected members of A including the static ones 

    callsSomePrivateMembers(b); // get to call them through a back-door 
} 
+0

+ 1のメタプログラミング、私は "私的アクセスが必要なメンバー機能"を取得していない。これは普通のメンバーの機能とは違いますか? – Simone

+0

私はそれを静的メンバー関数にすると、クラスのプライベートエリアにアクセスできることを意味しました。 – CashCow

4

一般的な例は、実際の例ではスレッドを作成するときです。共通スレッドAPI(POSIX/pthreads、Boost、およびWin32 CreateThread)にはすべて固有の署名が必要です。メンバ関数でそのシグネチャを取得する唯一の方法は、関数を静的にすることです。

+0

フリー機能は正常に動作します。 –

+0

@Matthieu:場合によっては、はい。ただし、スレッドラッパークラスを作成している場合はそうではありません。 –

+0

なぜ、コードの例を挙げることができますか分かりません。 (申し訳ありません:/) –

2

静的機能を使用するのが適切な場合は、質問を誤解して回答しました。

あなたは静的メンバー関数を意味しました。ここでは、静的メンバ関数を使用する場合の例だ - ...あなたのスレッドがあなたのクラスへのアクセス権を持つように、クラス内のスレッドの呼び出しをラップする:

static unsigned WINAPI ArchiveAgent::LogMsgPump(PVOID pData) 
{ 
    ArchiveAgent* pSmith = reinterpret_cast<ArchiveAgent*>(pData); 

    if(pSmith) 
     pSmith->LogMsgPump(); 
    else 
     return -1; 

    return 0; 
} 

unsigned WINAPI ArchiveAgent::LogMsgPump() 
{ 
    CoInitializeEx(NULL, COINIT_MULTITHREADED); 

    // .... 

    CoUninitialize(); 
    return 0; 
} 

ここでは、昔ながらの静的な機能のための私の答えでした.. 私は静的関数を使用します。静的関数は、その関数がクラスに属していないと意味があります。

これらの機能をカスタム名前空間に追加する傾向があります。

static HRESULT CreateFolder(CString & sPath) 
{ 
// create the destination folder if it doesn't already exist 

HRESULT hr  = S_OK; 
DWORD dwError = 0; 

if(sPath.GetLength() == 0 || sPath.GetLength() < 2)     
    return E_UNEXPECTED; 

if(GetFileAttributes((LPCWSTR) sPath) == INVALID_FILE_ATTRIBUTES) 
{   
    dwError = SHCreateDirectoryEx(NULL, (LPCWSTR)sPath, NULL); 

    if (dwError != ERROR_SUCCESS && dwError != ERROR_FILE_EXISTS && dwError != ERROR_ALREADY_EXISTS) 
     hr = HRESULT_FROM_WIN32(dwError); 
} 

return hr; 

}

+0

-1:彼は静的メンバー関数について質問しています。一般的に静的関数ではありません。 –

+0

それを逃した、答えを改訂する! –

+0

それは私にthoをマークする価値があったとは思わない! –

3

あなたがインスタンス化されたオブジェクトなし機能を使用することもできます。次の静的関数サンプルは、私がShellUtilsを呼び出す名前空間の一部です。また、関数が別の静的関数から呼び出された場合は、静的でなければなりません。

+0

それはなぜですか(2番目のポイント)?私はC++で動作しないので、その複雑さに欠けているかもしれませんが、少なくともC#とJavaの両方で、静的関数はインスタンスメンバをうまく使用できます - 必要なのは型のインスタンスを持つことだけです。 C++はこの点で異なっていますか? –

+0

"インスタンス化されていない関数を使用することができます" - 実際に質問に答える唯一の答えと思われる! –

2

シングルトンと呼ばれるデザインパターンを見てください。つまり、オブジェクトの作成を制限する方法の1つです。したがって、オブジェクトを作成する唯一の方法は、静的なC++メンバー関数を呼び出すことです。

2

典型的な例は、スタティックGetInstance()メソッドがクラスのシングルトンインスタンスを返すシングルトンクラスです。静的メンバ関数の

class Singleton 
{ 
    static Singleton instance; 

    private Singleton() 
    { 
    } 

    static Singleton & GetInstance() 
    { 
     if(instance == null) 
     instance = new Singleton(); 

     return instance; 
    } 
} 
+1

シングルトンパターンを実現するには、クラスの関数レベルの静的インスタンスを使用する方が適しています。 "Meyers Singleton"(http://www.devarticles.com/c/a/Cplusplus/C-plus-plus-In-Theory-The-Singleton-Pattern-Part-I/4/) –

+0

を追加しますか? ...シングルトンを使用することは、賛否両論を知った後でなければなりません。いくつかの例外的なシナリオから、シングルトンは通常、より多くの問題を生み出すことになります。考えてみてください...問題を解決してください...シングルトンを破棄してください... –

6

自然な使用場所は、クラスの内部にアクセスする必要があるため、フリー関数を使用できない場合です。これの最も典型的な例は、以下のビルダー関数です。 Fooのコンストラクタは、ビルダー関数以外の方法で構築されていないことを確認するために非公開です。

#include <iostream> 

class Foo { 
public: 
    static Foo* createFoo() {return new Foo();} 
private: 
    Foo() {} 
}; 

int main() { 
    //Foo nonBuiltFoo; //wont compile 
    Foo* freshFoo = Foo::createFoo(); 
    delete freshFoo; 
    return 0; 
} 

典型的な使用方法は前述のシングルトンパターンです。クラスの保護された部分と非公開の部分にアクセスする必要がないときは、静的メンバー関数は不要です(フリー関数を使用できます)が、クラスのドメイン内にあるときにも静的メンバー関数を使用するものもあります単一インスタンス上でこの関数を使用するための制限付き/論理

関連する問題