Когда использовать ключевое слово «статический» в классе C++?

StackOverflow https://stackoverflow.com/questions/800761

  •  03-07-2019
  •  | 
  •  

Вопрос

Код

 static void MyClass::ThreadEntryStatic()
 {
    //...
 }

 void MyClass::Begin()
 {
         CreateThread(..,ThreadEntryStatic,..);
 }

В каком случае нам следует использовать статику в классе?

Это было полезно?

Решение

Есть три места, где можно использовать ключевое слово static.Один из них находится в объявлении структуры/класса, когда этот контекст означает, что метод является методом класса, а не методом экземпляра.Это означает, что этот метод вызывается напрямую, и вам не нужен экземпляр.Из этого статического метода вы не можете получить доступ к переменным экземпляра.

В MyClass.h

struct MyClass
{
  static void ThreadEntryStatic();

  void Begin();
};

В MyClass.cpp

void MyClass::ThreadEntryStatic()
{
}

void MyClass::Begin()
{
  CreateThread(.., MyClass::ThreadEntryStatic, ...);
}

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

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

Другие советы

Если вы используете статические методы в нескольких потоках, вам нужно уделять очень пристальное внимание синхронизации вашего кода.По моему мнению, при многопоточном программировании я стараюсь использовать отдельный экземпляр моего объекта или рабочего элемента для каждого потока и вообще избегаю статических или общих данных любого типа.Конечно, это не всегда возможно, поэтому многопоточность остается одной из самых сложных областей программирования.

В качестве конкретного примера,

class Test{
      static void foo();      
};

static void Test::foo(){
    // code here
}

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

class Test{
      static void foo();      
};

void Test::foo(){
    // code here
}

Несколько человек затронули эту тему, но static используется для внутренней связи, не следует использовать, вместо этого следует использовать анонимное пространство имен:

namespace
{

void myInternallyLinkedFunction()
{
    // do something
}

int myInternallyLinkedInteger;

class myInternallyLinkedClass
{
public:
    void doSomething();
};

} // anon namespace


void myExternallyLinkedFunction()
{

    ++myInternallyLinkedInteger;
    myInternallyLinkedFunction();
    myInternallyLinkedClass x;
    x.doSomething();
}

Значения статических переменных сохраняются между вызовами функций.Проверять этот Запись MSDN для примеров.Определение и использование «статических» методов описано в ответе Криша.

Статику можно использовать при реализации одноэлементных классов, где вам нужно иметь только один экземпляр класса.Его использование зависит от контекста.

В вашем примере показан шаблон «обратный вызов потока статической функции-члена».Поскольку функция потока должна иметь подпись WINAPI, она не может быть обычной функцией-членом, а только статическим членом.Часто вы передаете это как параметр потока этому обратному вызову, а затем вызываете реального участника, выполняющего работу потока.

Статический член используется только один раз, а существует множество разных.Действительно сложно догадаться, в чем цель вашего вопроса.Вы решаете какую-то конкретную проблему или вас просто интересуют все возможные варианты использования статических членов или статических функций-членов?

Более полный пример «обратного вызова потока статической функции-члена»:

class MyClass
{

  /// background rendering thread
  int ThreadEntry()
  {
     // do the work here
  }

  /// static member callback "proxy"
  static DWORD WINAPI ThreadEntryStatic(void *param)
  {
    return ((EngineDD9 *)param)->ThreadEntry();
  }

  void SpawnThread()
  {
    CreateThread(.., ThreadEntryStatic, ...);
  }

};
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top