Вопрос был о равнине с функции, а не C ++ static
методы, как пояснено в комментариях.
Я понимаю, что такое static
переменная, но что такое static
функция?
И почему, если я объявляю функцию, скажем void print_matrix
, скажем так a.c
(БЕЗ a.h
) и включаю "a.c"
- я получаю "print_matrix@@....) already defined in a.obj"
, НО, если я объявлю ее так, как static void print_matrix
она компилируется?
ОБНОВЛЕНИЕ Просто чтобы прояснить ситуацию - я знаю, что в том числе .c
плохо, как многие из вас указали. Я просто делаю это, чтобы временно освободить место, main.c
пока у меня не появится лучшее представление о том, как сгруппировать все эти функции в нужные файлы .h
и .c
файлы. Просто временное, быстрое решение.
источник
Существует большая разница между статическими функциями в C и статическими функциями-членами в C ++. В Си статическая функция не видна за пределами ее единицы перевода, то есть объектного файла, в который она компилируется. Другими словами, создание статической функции ограничивает область ее применения. Вы можете думать о статической функции как о «закрытой» для ее файла * .c (хотя это не совсем правильно).
В C ++ «static» также может применяться к функциям-членам и данным-членам классов. Статический член данных также называется «переменной класса», в то время как нестатический член данных является «переменной экземпляра». Это терминология Smalltalk. Это означает, что существует только одна копия статического члена данных, совместно используемого всеми объектами класса, в то время как каждый объект имеет свою собственную копию нестатического члена данных. Таким образом, статический член данных по сути является глобальной переменной, то есть членом класса.
Нестатические функции-члены могут получить доступ ко всем данным-членам класса: статическим и нестатическим. Статические функции-члены могут работать только со статическими данными-членами.
Один из способов думать об этом состоит в том, что в C ++ статические члены-данные и статические функции-члены принадлежат не какому-либо объекту, а всему классу.
источник
Существует два варианта использования ключевого слова static в отношении функций в C ++.
Первый - пометить функцию как имеющую внутреннюю связь, чтобы на нее нельзя было ссылаться в других единицах перевода. Это использование устарело в C ++. Безымянные пространства имен являются предпочтительными для этого использования.
Второе использование в контексте класса. Если класс имеет статическую функцию-член, это означает, что функция является членом класса (и имеет обычный доступ к другим членам), но ее не нужно вызывать через определенный объект. Другими словами, внутри этой функции нет указателя «this».
источник
Пример минимальной работоспособной многофайловой области
Здесь я проиллюстрирую, как
static
влияет область определения функций в нескольких файлах.переменный ток
main.c
GitHub вверх по течению .
Скомпилируйте и запустите:
Вывод:
интерпретация
sf
, по одной для каждого файлаf
Как обычно, чем меньше область действия, тем лучше, поэтому всегда объявляйте функции,
static
если можете.В программировании на C файлы часто используются для представления «классов», а
static
функции представляют «частные» методы класса.Обычный шаблон C - это передача
this
структуры в качестве первого аргумента «метода», что в основном и делает C ++ под капотом.Что говорят об этом стандарты
C99 N1256 черновик 6.7.1 « Спецификаторы класса хранения» говорит, что
static
это «спецификатор класса хранения».6.2.2 / 3 «Связи идентификаторов» говорит, что
static
подразумеваетinternal linkage
:и 6.2.2 / 2 говорит, что
internal linkage
ведет себя как в нашем примере:где «единица перевода» - исходный файл после предварительной обработки.
Как GCC реализует это для ELF (Linux)?
С
STB_LOCAL
привязкой.Если мы скомпилируем:
и разберите таблицу символов с помощью:
вывод содержит:
таким образом, связывание - единственное существенное различие между ними.
Value
это просто их смещение в.bss
разделе, поэтому мы ожидаем, что он будет отличаться.STB_LOCAL
задокументировано в спецификации ELF по адресу http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html :что делает его идеальным выбором для представления
static
.Функции без статики есть
STB_GLOBAL
, а в спецификации сказано:что согласуется с ошибками ссылок в нескольких нестатических определениях.
Если мы запускаем оптимизацию с помощью
-O3
,sf
символ полностью удаляется из таблицы символов: его нельзя использовать извне. TODO зачем вообще хранить статические функции в таблице символов, когда нет оптимизации? Могут ли они быть использованы для чего-либо?Смотрите также
extern
является противоположностьюstatic
, и функции ужеextern
по умолчанию: Как я могу использовать extern для обмена переменными между исходными файлами?C ++ анонимные пространства имен
В C ++ вы можете захотеть использовать анонимные пространства имен вместо статических, что дает аналогичный эффект, но дополнительно скрывает определения типов: Безымянный / анонимный пространства имен против статических функций
источник
void f() { puts("sf"); }
(то есть два определенияf()
) вызывает неопределенное поведение без необходимости диагностики. Это проблема качества компоновщика, чтобы увидеть сообщение об ошибке.Ниже приведены простые функции C - в классе C ++ модификатор «static» имеет другое значение.
Если у вас есть только один файл, этот модификатор не имеет абсолютно никакого значения. Разница заключается в больших проектах с несколькими файлами:
В C каждый «модуль» (комбинация sample.c и sample.h) компилируется независимо, и после этого каждый из этих скомпилированных объектных файлов (sample.o) связывается компоновщиком с исполняемым файлом.
Допустим, у вас есть несколько файлов, которые вы включаете в свой основной файл, и два из них имеют функцию, которая используется только для удобства,
add(int a, b)
- для удобства компилятор легко создает объектные файлы для этих двух модулей, но компоновщик выдаст ошибку, потому что он находит две функции с одинаковыми именами и не знает, какую из них использовать (даже если нечего связывать, потому что они не используются где-то еще, кроме как в его собственном файле).Вот почему вы делаете эту функцию, которая используется только внутри, статической функцией. В этом случае компилятор не создает типичный флаг «Вы можете связать эту вещь» для компоновщика, так что компоновщик не видит эту функцию и не генерирует ошибку.
источник
Первое: вообще плохая идея включать
.cpp
файл в другой файл - это приводит к таким проблемам :-) Обычный способ - создать отдельные модули компиляции и добавить файл заголовка для включенного файла.Во-вторых:
C ++ имеет здесь некоторую запутанную терминологию - я не знал об этом, пока не было указано в комментариях.
а)
static functions
- унаследовано от C, и о чем вы тут говорите. Вне любого класса. Статическая функция означает, что она не видна вне текущего модуля компиляции - поэтому в вашем случае a.obj имеет копию, а ваш другой код имеет независимую копию. (Вздутие конечного исполняемого файла с несколькими копиями кода).б)
static member function
- что объектная ориентация называет статическим методом . Живет внутри класса. Вы вызываете это с помощью класса, а не через экземпляр объекта.Эти два разных определения статических функций совершенно разные. Будьте осторожны - здесь будут драконы.
источник
статические определения функций помечают этот символ как внутренний. Таким образом, он не будет виден для ссылок извне, а только для функций в том же модуле компиляции, обычно в том же файле.
источник
Статическая функция - это функция, которая может быть вызвана в самом классе, в отличие от экземпляра класса.
Например, нестатический будет:
Этот метод работает с экземпляром класса, а не с самим классом. Однако у вас может быть статический метод, который может работать без экземпляра. Это иногда используется в шаблоне Factory:
источник
Незначительное: статические функции видны единице перевода, которая для большинства практических случаев является файлом, в котором определена функция. Получаемая ошибка обычно называется нарушением правила единого определения.
Стандарт, вероятно, говорит что-то вроде:
Это C-взгляд на статические функции. Это не рекомендуется в C ++, однако.
Кроме того, в C ++ вы можете объявлять статические функции-члены. В основном это метафункции, то есть они не описывают / не изменяют поведение / состояние конкретного объекта, а воздействуют на весь класс. Кроме того, это означает, что вам не нужно создавать объект для вызова статической функции-члена. Кроме того, это также означает, что вы получаете доступ к статическим переменным-членам только из такой функции.
Я бы добавил к примеру Parrot шаблон Singleton, который основан на статической функции-члене такого типа, чтобы получать / использовать один объект в течение всей жизни программы.
источник
Ответ на статическую функцию зависит от языка:
1) В языках без OOPS, таких как C, это означает, что функция доступна только внутри файла, в котором она определена.
2) В языках с OOPS, таких как C ++, это означает, что функция может быть вызвана непосредственно в классе без создания его экземпляра.
источник
static
имеет файловую область, как и в C.Так как статическая функция видна только в этом файле. Фактически, компилятор может сделать некоторую оптимизацию для вас, если вы объявите «static» какой-либо функции.
Вот простой пример.
main.c
И скомпилировать с
Вы увидите, что это не удалось. Потому что вы даже не реализуете функцию ghost ().
Но что, если мы используем следующую команду?
Это успех , и эту программу можно выполнить нормально.
Почему? Есть 3 ключевых момента.
Только если все эти 3 условия выполнены, вы можете пройти компиляцию. Из-за этого «статического» объявления компилятор может подтвердить, что test () НИКОГДА не будет вызываться в другом файле. Ваш компилятор может удалить test () при компиляции. Поскольку нам не нужен test (), не имеет значения, определен или реализован ghost ().
источник
Давайте начнем с самого начала.
Все это основано на том, что называется «связь»:
Если функция определена без спецификатора класса хранилища, функция
extern
по умолчанию имеет все связи:Это означает, что - если ваша программа состоит из нескольких единиц перевода / исходных файлов (
.c
или.cpp
) - функция видна во всех единицах перевода / исходных файлах, которые есть в вашей программе.Это может быть проблемой в некоторых случаях. Что делать, если вы хотите использовать две разные функции (определения), но с одинаковым именем функции в двух разных контекстах (на самом деле в контексте файла).
В C и C ++
static
квалификатор класса хранения, примененный к функции в области видимости файла (не статическая функция-член класса в C ++ или функция в другом блоке), теперь помогает и означает, что соответствующая функция видна только внутри модуль перевода / исходный файл, в котором он был определен, а не в других TLU / файлах.Таким образом,
static
функция имеет смысл только тогда, когда:Ваша программа содержит несколько единиц перевода / исходных файлов (
.c
или.cpp
).а также
Вы хотите ограничить область действия функции файлом, в котором определена определенная функция.
Если оба эти требования не совпадают, вам не нужно задумываться о том, чтобы квалифицировать функцию как
static
.Примечания стороны:
Как уже упоминалось,
static
функция A не имеет абсолютно никакой разницы между C и C ++, поскольку это функция C ++, унаследованная от C.Неважно, что в сообществе C ++ идут душераздирающие дебаты об обесценивании квалифицирующих функций
static
по сравнению с использованием вместо этого безымянных пространств имен , сначала инициализированных неуместным абзацем в стандарте C ++ 03, объявляя об использовании статические функции как устаревшие, которые вскоре были пересмотрены самим комитетом и удалены в C ++ 11.Это было предметом различных вопросов SO:
Безымянное / анонимное пространство имен против статических функций
Превосходство безымянного пространства имен над статическим?
Почему безымянное пространство имен является «превосходящей» альтернативой статическому?
Устаревание статического ключевого слова ... не более?
На самом деле, это не считается устаревшим в соответствии со стандартом C ++. Таким образом, использование
static
функций все еще законно. Даже если у неназванных пространств имен есть свои преимущества, обсуждение использования или неиспользования статических функций в C ++ является предметом единого мнения (основанного на мнениях), и тот, который не подходит для данного веб-сайта.источник