2011-02-07 3 views
10

Возможные Дубликаты:
Where would you use a friend function vs a static function?
C++: static member functionsКогда использовать статическую функцию-член?

Когда это целесообразно использовать статическую функцию-член в C++? Пожалуйста, дайте мне пример в реальном мире.

+2

Что с тегом 'oops'? – Maxpm

+2

Я отредактировал вопрос, так как я думаю, что автор просто означает «ООП» или Object-Orientated-Programming. –

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

Здесь был мой ответ на простые старые статические функции .. Я использую статические функции, когда для этой функции не имеет смысла принадлежать классу.

Обычно я обычно добавляю эти функции в собственное пространство имен. Следующая статическая выборочная функция является частью пространства имен я называю 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; 

}

+0

-1: Он спрашивает о статических функциях члена. Не статические функции вообще. –

+0

пропустил это, пересмотрит ответ! –

+0

не думаю, что это стоило мне пометить! –

3

Вы можете использовать функцию без объекта реализованного. Также, если функция вызывается из другой статической функции, она должна быть статической.

+0

Почему это (второй пункт)? Я признаю, что я не работаю на C++, так что может быть недостаток в его тонкостях, но, по крайней мере, на C# и Java, статические функции могут просто использовать экземпляры экземпляров - все, что нужно, - это иметь экземпляр типа , Является ли C++ другим в этом отношении? –

+0

«Вы можете использовать функцию без объекта, созданного экземпляром» - это, кажется, единственный ответ, который на самом деле отвечает на вопрос! –

2

Пожалуйста, найдите шаблон дизайна, называемый singleton. Короче говоря, это один из способов ограничить создание объекта. Таким образом, единственный способ создать объект - вызвать функцию члена C++, которая является статической.

2

Типичным примером может быть одиночный класс, в котором статический метод GetInstance() возвращает экземпляр singleton класса.

class Singleton 
{ 
    static Singleton instance; 

    private Singleton() 
    { 
    } 

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

     return instance; 
    } 
} 
+1

Лучше использовать статический экземпляр класса уровня функции для выполнения шаблона Singleton. См. «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; 
} 

Типичное использование ранее упомянутого шаблона Singleton. Когда вам не нужно обращаться к защищенным и частным частям класса, статические функции-члены не нужны (могут использоваться свободные функции), но есть некоторые, которые используют статические функции-члены также, когда они находятся в домене класса, но не ограничено/логично использовать функцию в одном экземпляре.

Смежные вопросы