Статические методы класса



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



Что это за фича такая. Это совершенно обычная функция, практически ничем не отличающаяся от функции, определенной прямо сразу после класса. Единственное семантическое отличие - статические методы имеют доступ к приватным и защищенным мемберам(полям и методам) конкретного класса. Оттого она и называется методом, потому что как бы привязана к классу возможностью подсматривать в скрытые поля.



Термин цикл жизни не совсем корректно применять к функциям, но я все же попробую. Жизнь обычного метода, точнее время, когда его можно использовать, ограничено жизнью объекта класса. Есть объект - можно вызвать метод. Нет объекта - нельзя. Со статическими методами другая петрушка. Они доступны всему коду, который видит определение класса, и вызвать их можно в любое время. Даже до входа в main(не то, чтобы это сильно необычно, но утверждение все равно верное).



По поводу линковки тут все просто - тип линковки совпадает с линковкой класса. По умолчанию она внешняя. Но какой-нибудь anonymous namespace может это изменить. Опять же параллели с обычными свободными функциями.



Пока писал этот пост, мне в голову пришла интересная идея. А что, если рассматривать статический метод не как свободную функцию, прикрепленную к классу? Точнее даже не так. А что если рассматривать ВСЕ методы класса, как обычные свободные функции с возможностью заглядывать с приватные члены? На самом деле ведь так и есть: нет никакого метода, в языке С нет такого понятия(это я к тому, что все плюсовые оопшные концепции реализованы с помощью сишных инструментов). Зато есть функции. А класс - это просто данные и функции, которым разрешили работать с этими данными. Теперь вопрос: как с этой точки зрения отличаются статические и нестатические методы?



И на самом деле в базе они отличаются лишь одной вещью: в нестатические методы передается первым параметром this(указатель на объект, из которого вызывается метод), а в статические не передается. И ВСЁ! Все остальные отличия идут от этого.



Например, статические методы не могут быть виртуальными. Оно и понятно, ведь у них нет объекта, из которого они всегда могут достать указатель vptr.



Или еще статические методы не могут быть помечены const. Не удивительно. Ведь на самом деле константные методы - функции, в которые передали const Type *, то есть указатель на константный объект. А его не завезли в статический метод. По этой же причине volatile к таким методам не применим.



Статический метод может быть сохранен в обычный указатель на функцию. Но не в указатель на метод (можете посмотреть пост про него). И ничего странного здесь нет, потому что указателю на метод нужен объект, а статическому методы - нет. Кстати, обычный метод тоже можно вызывать как через указатель на метод, так и через обычный указатель на функцию(ссылочка на посты про это тут и тут).



Попробую даже продемонстрировать это. Возьмем класс и определим у него статический и нестатический методы, которые будут делать одно и то же: увеличивать поле класса за счет входного параметра. Чтобы сделать тоже самое для статического метода, придется ему передать указатель на объект касса. И мы можем использовать для вызова обоих методов один и тот же тип указателя на функцию(см на картинку). Получается, что в нестатическом методе просто к именам, которые совпадают с членами или методами класса, компилятор неявно приписывается this->. Вот и вся история.



Так что теперь вы точно знаете, что на самом деле такое статические методы. Надеюсь, что даже опытные читатели канала взлянули на это с другого угла.



See all sides of the coin. Stay cool.



#compiler #cppcore #hardcore