Static void что это
Всем привет. На одном из код-ревью я столкнулся с мыслью, что многие, а чего скрывать и я сам, не то чтобы хорошо понимаем когда нужно использовать ключевое слова static. В данной статье я хотел бы поделиться своими знаниями и информацией по поводу ключевого слова static. Статья будет полезна как начинающим программистам, так и людям, работающим с языком С++. Для понимания статьи у вас должны быть знания о процессе сборки проектов и владение языком С/С++ на базовом уровне. Кстати, static используется не только в С++, но и в С. В этой статье я буду говорить о С++, но имейте в виду, что всё то, что не связано с объектами и классами, в основном применимо и к языку С.
Что такое static?
Где используется?
Ниже приведена схема, как и где используется static в программе.
А теперь я постараюсь детально описать все то, что изображено на схеме. Поехали!
Статические переменные внутри функции
Если не использовать static в строке 4, выделение памяти и инициализация переменной count происходит при каждом вызове функции counter(), и уничтожается каждый раз, когда функция завершается. Но если мы сделаем переменную статической, после инициализации (при первом вызове функции counter()) область видимости count будет до конца функции main(), и переменная будет хранить свое значение между вызовами функции counter().
Статические объекты класса
В строке 3 мы создаем класс Base с конструктором (строка 5) и деструктором (строка 8). При вызове конструктора либо деструктора мы выводим название метода класса в консоль. В строке 14 мы создаем статический объект obj класса Base. Создание этого статического объекта будет происходить только при первом вызове функции foo() в строке 18.
Из-за того, что объект статический, деструктор вызывается не при выходе из функции foo() в строке 15, а только при завершении программы, т.к. статический объект разрушается при завершении программы. Ниже приведен пример той же программы, за исключением того, что наш объект нестатический.
Если мы уберем static при создании переменной в функции foo(), то разрушение объекта будет происходить в строке 15 при каждом вызове функции. В таком случае вывод программы будет вполне ожидаемый для локальной переменной с выделенной памятью на стеке:
Статические члены класса
В сравнении с предыдущими вариантами использования, статические члены класса немного сложнее для понимания. Давайте разберемся, почему. Предположим, у нас есть следующая программа:
В нашем примере мы создали класс А (строка 3) и класс В (строка 9) со статическими членами класса (строка 15). Мы предполагаем, что при создании объекта b в строке 19 будет создан объект a в строке 15. Так бы и произошло, если бы мы использовали нестатические члены класса. Но вывод программы будет следующим:
Причиной такого поведения является то, что статические члены класса не инициализируются с помощью конструктора, поскольку они не зависят от инициализации объекта. Т.е. в строке 15 мы только объявляем объект, а не определяем его, так как определение должно происходить вне класса с помощью оператора разрешения области видимости (::). Давайте определим члены класса B.
Теперь, после того как мы определили наш статический член класса в строке 18, мы можем увидеть следующий результат программы:
Constructor A
Constructor B
Destructor B
Destructor A
Нужно помнить, что член класса будет один для всех экземпляров класса B, т.е. если мы создали три объекта класса B, то конструктор статического члена класса будет вызван только один раз. Вот пример того, о чем я говорю:
Constructor A
Constructor B1
Constructor B2
Constructor B3
Destructor B3
Destructor B2
Destructor B1
Destructor A
Статические функции
Для того чтобы исправить данную проблему, одну из функций мы объявим статической. Например эту:
В этом случае вы говорите компилятору, что доступ к статическим функциям ограничен файлом, в котором они объявлены. И он имеет доступ только к функции sum() из math.cpp файла. Таким образом, используя static для функции, мы можем ограничить область видимости этой функции, и данная функция не будет видна в других файлах, если, конечно, это не заголовочный файл (.h).
Статические функции-члены класса (методы)
Статическую функцию-член вы можете использовать без создания объекта класса. Доступ к статическим функциям осуществляется с использованием имени класса и оператора разрешения области видимости (::). При использовании статической функции-члена есть ограничения, такие как:
В классе A в строке 8 у нас есть статическая функция-член foo(). В строке 14, мы вызываем функцию используя имя класса и оператор разрешения области видимости и получаем следующий результат программы:
Из вывода видно, что никакого создания объекта нет и конструктор/деструктор не вызывается.
Если бы метод foo() был бы нестатическим, то компилятор выдал бы ошибку на выражение в строке 14, т.к. нужно создать объект для того, чтобы получить доступ к его нестатическим методам.
Заключение
В одной статье в интернете я нашел совет от автора – «Используйте static везде, где только можно». Я хотел бы написать, почему так делать не стоит, а стоит использовать только в случае необходимости.
Ключевое слово static
Иногда требуется определить такой член класса, который будет использоваться независимо от всех остальных объектов этого класса. Как правило, доступ к члену класса организуется посредством объекта этого класса, но в то же время можно создать член класса для самостоятельного применения без ссылки на конкретный экземпляр объекта. Для того чтобы создать такой член класса, достаточно указать в самом начале его объявления ключевое слово static.
Если член класса объявляется как static, то он становится доступным до создания любых объектов своего класса и без ссылки на какой-нибудь объект. С помощью ключевого слова static можно объявлять как переменные, так и методы. Наиболее характерным примером члена типа static служит метод Main(), который объявляется таковым потому, что он должен вызываться операционной системой в самом начале выполняемой программы.
Для того чтобы воспользоваться членом типа static за пределами класса, достаточно указать имя этого класса с оператором-точкой. Но создавать объект для этого не нужно. В действительности член типа static оказывается доступным не по ссылке на объект, а по имени своего класса.
Переменные, объявляемые как static, по существу, являются глобальными. Когда же объекты объявляются в своем классе, то копия переменной типа static не создается. Вместо этого все экземпляры класса совместно пользуются одной и той же переменной типа static. Такая переменная инициализируется перед ее применением в классе.
Пример использования ключевого слова static:
На применение методов типа static накладывается ряд следующих ограничений:
В методе типа static должна отсутствовать ссылка this, поскольку такой метод не выполняется относительно какого-либо объекта
В методе типа static допускается непосредственный вызов только других методов типа static, но не метода экземпляра из того самого же класса. Дело в том, что методы экземпляра оперируют конкретными объектами, а метод типа static не вызывается для объекта. Следовательно, у такого метода отсутствуют объекты, которыми он мог бы оперировать
Аналогичные ограничения накладываются на данные типа static. Для метода типа static непосредственно доступными оказываются только другие данные типа static, определенные в его классе. Он, в частности, не может оперировать переменной экземпляра своего класса, поскольку у него отсутствуют объекты, которыми он мог бы оперировать
Статические конструкторы
Конструктор можно также объявить как static. Статический конструктор, как правило, используется для инициализации компонентов, применяемых ко всему классу, а не к отдельному экземпляру объекта этого класса. Поэтому члены класса инициализируются статическим конструктором до создания каких-либо объектов этого класса:
Обратите внимание на то, что конструктор типа static вызывается автоматически, когда класс загружается впервые, причем до конструктора экземпляра. Из этого можно сделать более общий вывод: статический конструктор должен выполняться до любого конструктора экземпляра. Более того, у статических конструкторов отсутствуют модификаторы доступа — они пользуются доступом по умолчанию, а следовательно, их нельзя вызывать из программы.
Статические классы
Класс можно объявлять как static. Статический класс обладает двумя основными свойствами. Во-первых, объекты статического класса создавать нельзя. И во-вторых, статический класс должен содержать только статические члены. Статический класс создается по приведенной ниже форме объявления класса, видоизмененной с помощью ключевого слова static.
Статические классы применяются главным образом в двух случаях. Во-первых, статический класс требуется при создании метода расширения. Методы расширения связаны в основном с языком LINQ. И во-вторых, статический класс служит для хранения совокупности связанных друг с другом статических методов:
Стоит отметить, что для статического класса не допускается наличие конструктора экземпляра, но у него может быть статический конструктор.
10 заметок о модификаторе Static в Java
Статические поля
Статический блок
Статический метод
Статический класс в Java
Что должен знать каждый программист о модификаторе Static в Java
Вы НЕ можете получить доступ к НЕ статическим членам класса, внутри статического контекста, как вариант, метода или блока. Результатом компиляции приведенного ниже кода будет ошибка:
В отличие от локальных переменных, статические поля и методы НЕ потокобезопасны (Thread-safe) в Java. На практике это одна из наиболее частых причин возникновения проблем связанных с безопасностью мультипоточного программирования. Учитывая что каждый экземпляр класса имеет одну и ту же копию статической переменной, то такая переменная нуждается в защите — «залочивании» классом. Поэтому при использовании статических переменных, убедитесь, что они должным образом синхронизированы (synchronized), во избежание проблем, например таких как «состояние гонки» (race condition).
Статические методы имеют преимущество в применении, т.к. отсутствует необходимость каждый раз создавать новый объект для доступа к таким методам. Статический метод можно вызвать, используя тип класса, в котором эти методы описаны. Именно поэтому, подобные методы как нельзя лучше подходят в качестве методов-фабрик ( factory ), и методов-утилит ( utility ). Класс java.lang.Math — замечательный пример, в котором почти все методы статичны, по этой же причине классы-утилиты в Java финализированы ( final ).
Другим важным моментом является то, что вы НЕ можете переопределять ( Override ) статические методы. Если вы объявите такой же метод в классе-наследнике ( subclass ), т.е. метод с таким же именем и сигнатурой, вы лишь «спрячете» метод суперкласса ( superclass ) вместо переопределения. Это явление известно как сокрытие методов ( hiding methods ). Это означает, что при обращении к статическому методу, который объявлен как в родительском, так и в дочернем классе, во время компиляции всегда будет вызван метод исходя из типа переменной. В отличие от переопределения, такие методы не будут выполнены во время работы программы. Рассмотрим пример:
Внутри родительского класса/статического метода
Модификатор static также может быть объявлен в статичном блоке, более известным как «Статический блок инициализации» ( Static initializer block ), который будет выполнен во время загрузки класса. Если вы не объявите такой блок, то Java соберёт все статические поля в один список и выполнит его во время загрузки класса. Однако, статичный блок НЕ может пробросить перехваченные исключения, но может выбросить не перехваченные. В таком случае возникнет «Exception Initializer Error». На практике, любое исключение возникшее во время выполнения и инициализации статических полей, будет завёрнуто Java в эту ошибку. Это также самая частая причина ошибки «No Class Def Found Error», т.к. класс не находился в памяти во время обращения к нему.
Полезно знать, что статические методы связываются во время компиляции, в отличие от связывания виртуальных или не статических методов, которые связываются во время исполнения на реальном объекте. Следовательно, статические методы не могут быть переопределены в Java, т.к. полиморфизм во время выполнения не распространяется на них. Это важное ограничение, которое необходимо учитывать, объявляя метод статическим. В этом есть смысл, только тогда, когда нет возможности или необходимости переопределения такого метода классами-наследниками. Методы-фабрики и методы-утилиты хорошие образцы применения модификатора static. Джошуа Блох выделил несколько преимуществ использования статичного метода-фабрики перед конструктором, в книге «Effective Java», которая является обязательной для прочтения каждым программистом данного языка.
На этом всё. Все вышеперечисленные пункты о модификаторе static в Java обязан знать каждый программист. В данной статье была рассмотрена базовая информация о статических переменных, полях, методах, блоках инициализации и импорте. В том числе некоторые важные свойства, знание которых является критичным при написании и понимании программ на Java. Я надеюсь, что каждый разработчик доведёт свои навыки использования статических концептов до совершенства, т.к. это очень важно для серьёзного программирования.»
Статические классы и члены статических классов (Руководство по программированию в C#)
Создание нестатического класса, который допускает создание только одного экземпляра самого себя, см. в документе Реализация Singleton в C#.
Ниже приведены основные возможности статического класса.
Содержит только статические члены.
Создавать его экземпляры нельзя.
По сути, создание статического класса аналогично созданию класса, содержащего только статические члены и закрытый конструктор. Закрытый конструктор не допускает создания экземпляров класса. Преимущество применения статических классов заключается в том, что компилятор может проверить отсутствие случайно добавленных членов экземпляров. Таким образом, компилятор гарантирует невозможность создания экземпляров таких классов.
Статические классы запечатаны, поэтому их нельзя наследовать. Они не могут наследовать ни от каких классов, кроме Object. Статические классы не могут содержать конструктор экземпляров. Однако они могут содержать статический конструктор. Нестатические классы также должен определять статический конструктор, если класс содержит статические члены, для которых нужна нетривиальная инициализация. Дополнительные сведения см. в разделе Статические конструкторы.
Пример
Ниже приведен пример статического класса, содержащего два метода, преобразующих температуру по Цельсию в температуру по Фаренгейту и наоборот.
Статический члены
Нестатический класс может содержать статические методы, поля, свойства или события. Статический член вызывается для класса даже в том случае, если не создан экземпляр класса. Доступ к статическому члены всегда выполняется по имени класса, а не экземпляра. Существует только одна копия статического члена, независимо от того, сколько создано экземпляров класса. Статические методы и свойства не могут обращаться к нестатическим полям и событиям в их содержащем типе, и они не могут обращаться к переменной экземпляра объекта, если он не передается явно в параметре метода.
Более привычно объявление нестатического класса с несколькими статическими членами, чем объявление всего класса как статического. Статические поля обычно используются для следующих двух целей: хранение счетчика числа созданных объектов или хранение значения, которое должно совместно использоваться всеми экземплярами.
Статические методы могут быть перегружены, но не переопределены, поскольку они относятся к классу, а не к экземпляру класса.
C# не поддерживает статические локальные переменные (то есть переменные, объявленные в области действия метода).
Для объявления статических методов класса используется ключевое слово static перед возвращаемым типом члена, как показано в следующем примере:
Статические члены инициализируются перед первым доступом к статическому члену и перед вызовом статического конструктора, если таковой имеется. Для доступа к члену статического класса следует использовать имя класса, а не имя переменной, указывая расположение члена, как показано в следующем примере:
Если класс содержит статические поля, должен быть указан статический конструктор, который инициализирует эти поля при загрузке класса.
Спецификация языка C#
Дополнительные сведения см. в разделах Статические классы и Члены экземпляра и статические члены в документации Предварительная спецификация C# 6.0. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.
BestProg
Статические классы, методы, переменные. Статические конструкторы. Ключевое слово static
Содержание
Поиск на других ресурсах:
1. Какие элементы языка программирования C# можно объявлять статическими?
В языке программирования C# статическими могут быть:
⇑
2. Понятие статического класса. Какие особенности использования статических классов в программах на C#? Ключевое слово static
С точки зрения синтаксиса C# статический класс – это класс, который объявляется с ключевым словом static.
Общая форма объявления статического класса:
где ClassName – имя статического класса.
⇑
3. Свойства статического класса
Реализация программного кода статического класса ничем не отличается от программного кода обычного класса за исключением двух основных свойств. В сравнении с нестатическим классом, статический класс имеет следующие свойства (отличия):
⇑
4. Примеры, которые демонстрируют свойства статического класса
Если попробовать создать объект статического класса
то возникнет ошибка компиляции с сообщением:
то во время компиляции компилятор выдаст следующую ошибку:
⇑
5. Примеры статических классов
Программный код классов Count и Methods следующий:
Если в данном примере класс Count объявить как нестатический (без ключевого слова static )
то результат работы программы не изменится. Статическую переменную Count.count можно использовать как общий ресурс.
Пример 2. Пример демонстрирует использование статического метода в нестатическом классе. Статический метод выступает общим ресурсом, который выполняет некоторую общую работу.
⇑
6. Какие преимущества применения статических классов, методов и переменных в программах на C#?
Статические классы, методы и переменные эффективны в следующих случаях:
⇑
7. Чем отличается вызов статического метода от нестатического?
В любом нестатическом классе могут быть объявлены как статические методы, так и нестатические. Отличие между вызовом статического и нестатического метода класса состоит в следующем:
Ниже демонстрируется вызов и использование этих методов:
Как видно из вышеприведенного кода, чтобы вызвать статический метод некоторого класса, перед его именем нужно указать имя этого класса.
⇑
8. Можно ли объявить скрытый ( private ) статический член в некотором классе?
Да можно. В этом случае этот статический член класса будет доступным только в границах этого класса, то есть из методов этого класса. Доступ из методов других классов будет невозможен.
⇑
Да можно. В этом случае, доступ к статического члену класса будут иметь методы класса, которые унаследованы от данного класса.
⇑
10. Может ли нестатический класс содержать статические переменные и статические методы?
Да может. Примеры использования статических методов в нестатическом классе приведены в пунктах 5 и 7.
⇑
11. Можно ли объединять статические и нестатические методы в одном классе?
Да, можно. Но только в нестатическом классе. Если класс объявлен как статический, то все методы и переменные класса должны быть также статическими (см. п. 4 — Пример 2).
В нижеследующем коде продемонстрирован доступ к скрытой статической переменной t класса CMyClass
Данный пример хорошо демонстрирует, как можно организовать работу с общими, скрытыми данными класса.
⇑
12. Можно ли в статическом методе статического класса создать объект нестатического класса?
⇑
13. Что такое статические конструкторы? Пример
Статические конструкторы позволяют инициализировать статические переменные класса.
Пример. Демонстрируется объявление статического конструктора в классе.
Демонстрация работы класса CCount в некотором методе
⇑
14. Какие правила (особенности) использования статических конструкторов?
При использовании статических конструкторов нужно обратить внимание на следующие правила:
⇑
15. Можно ли из статических конструкторов инициализировать нестатические переменные класса?
Нет, нельзя. Из статических конструкторов можно инициализировать только статические переменные этого же класса. Если в этом классе также объявляются нестатические переменные, то доступа к ним из статических конструкторов нету.