2011-02-07 124 views
10

可能顯示的文件:
Where would you use a friend function vs a static function?
C++: static member functions何時使用靜態成員函數?

時候適合使用C++中的靜態成員函數?請給我一個真實世界的例子。

+2

什麼是'oops`標籤? – Maxpm 2011-02-07 12:16:20

+2

我編輯的問題,因爲我認爲作者只是意味着「面向對象」,或面向對象的編程。 – 2011-02-07 12:18:35

+1

http://stackoverflow.com/questions/4723143/c-static-member-functions – Mahesh 2011-02-07 12:20:25

回答

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 
} 
4

一個常見的例子,你會發現(在現實世界的例子)是當你創建一個線程。公共線程API(POSIX/pthreads,Boost和Win32 CreateThread)都需要特定的簽名。在成員函數中獲得簽名的唯一方法是使函數靜態。

+0

自由功能可以很好地工作。 – 2011-02-07 12:42:13

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

這是我對普通的舊靜態函數答案.. 我使用靜態函數,它對於該函數屬於一個類沒有意義。

我通常傾向於將這些函數添加到自定義名稱空間。下面的靜態函數樣本是命名空間,我稱之爲ShellUtils的一部分:

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; 

}

3

您可能需要使用的功能,而不實例化一個對象。另外,如果函數是從另一個靜態函數調用的,它必須是靜態的。

2

請查閱一個名爲singleton的設計模式。簡而言之,它是限制對象創建的一種方法。因此,創建對象的唯一方法是調用靜態的C++成員函數。

2

一個典型的例子可以是一個單例類,其中靜態GetInstance()方法返回該類的單例實例。靜態成員函數

class Singleton 
{ 
    static Singleton instance; 

    private Singleton() 
    { 
    } 

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

     return instance; 
    } 
} 
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; 
} 

一個典型的用法是前面提到的Singleton模式。當你不必訪問類的受保護和私有部分時,靜態成員函數不是必需的(可以使用自由函數),但是有一些靜態成員函數也在類的域內時使用靜態成員函數限制/邏輯在單個實例上使用該功能。