Когда следует писать ключевое слово "static" перед функцией, отличной от члена?

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

1) Когда следует писать ключевое слово static перед функцией, отличной от члена?

2) Опасно ли определять статическую не-членную функцию в заголовке? Почему (не)?


(побочный вопрос)

3) Можно ли определить класс в файле заголовка определенным образом, чтобы он был доступен только в блоке перевода, где вы его используете в первую очередь?

(Причина, по которой я спрашиваю об этом, заключается в том, что я изучаю STL, и это может быть хорошим решением для моих предикатов и т.д. (возможно, функторов), так как я не люблю определять функции, отличные от функций-членов в файл cpp)

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

ИЗМЕНИТЬ

Другой вопрос, который возник при просмотре ответов:

4). Многие говорят мне, что я должен объявить статическую функцию в заголовке и определить ее в исходном файле. Но статическая функция уникальна для единицы перевода. Как связующее звено знает , что единица перевода является уникальной, поскольку файлы заголовков напрямую не связаны с исходным файлом (только при их включении)?

Ответ 1

static, как я думаю, вы используете его, является средством скрытия символа. Объявленные функции static не имеют глобальной видимости (Unix-подобный nm покажет их как "t", а не "T" ). Эти функции нельзя вызывать из других единиц перевода.

Для С++ static в этом смысле был заменен более или менее анонимным пространством имен, например

static int x = 0;

довольно эквивалентно

namespace {
  int x = 0;
}

Обратите внимание, что анонимное пространство имен уникально для каждой единицы компиляции.

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

namespace {
 class Foo{};
}

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

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

Обратите внимание, что все функции, не являющиеся членами, объявленными как inline, также по умолчанию static. Это наиболее распространенное (и неявное) использование static. Что касается пункта 2, то определение функции static, но не inline в заголовке - это довольно угловой случай: он не опасен сам по себе, но он настолько редко полезен, что это может сбивать с толку. Такая функция может быть или не быть выбрана в каждой единицы перевода. Компилятор может генерировать предупреждения, если вы фактически не вызываете функцию в некоторых TU. И если эта статическая функция имеет в себе статическую переменную, вы получаете отдельную переменную на единицу перевода даже с одним определением в одном .h, который может запутать. Там не так много (не встроенных) случаев использования.

Что касается пункта 4, я подозреваю, что эти люди объединяют значение статической функции-члена static с значением значения привязки static. Это так же полезно, как и любое использование анонимного пространства имен для последнего.

Ответ 2

Ключевое слово "static" перегружено, чтобы означать несколько разных вещей:

  • Он может контролировать видимость (как C, так и С++)

  • Он может сохранять переменную между вызовами подпрограмм (как C, так и С++)

    ... и...

  • Он может сделать метод или член применимыми ко всему классу (а не только к экземпляру класса: только С++)

Короткий ответ: лучше не использовать ЛЮБОЙ языковой инструмент, если

a) вы уверены, что вам это нужно

b) вы уверены, что знаете, что делаете (т.е. вы знаете, ПОЧЕМУ вам это нужно)

Абсолютно ничего плохого в объявлении статических переменных или автономных функций в файле .cpp. Объявление статической переменной или автономной функции в заголовке, вероятно, неразумно. И если вам действительно нужно "статическое" для функции класса или члена класса, то заголовок, возможно, является ЛУЧШИМ местом для его определения.

Здесь хорошая ссылка:

http://www.cprogramming.com/tutorial/statickeyword.html

'Надеюсь, что поможет

Ответ 3

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

Этот же вопрос задавали cplusplus.com