Когда я должен написать ключевое слово «static» перед функцией, не являющейся членом? - PullRequest
21 голосов
/ 07 декабря 2011

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

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

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


(дополнительный вопрос)

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

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

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

EDIT

Еще один вопрос, который возник при просмотре некоторых ответов:

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

Ответы [ 3 ]

18 голосов
/ 07 декабря 2011

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

Для C ++ 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.,Как и любая другая причина для использования анонимного пространства имен для последнего.

4 голосов
/ 07 декабря 2011

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

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

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

    ... и ...

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

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

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

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

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

Вот хорошая ссылка:

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

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

1 голос
/ 07 декабря 2011

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

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

...