Я пытаюсь использовать встроенную функцию.
Нет смысла использовать extern
с функцией. См. срок хранения - связь . Функции имеют внешнюю связь по умолчанию; чтобы не иметь внешней связи, нужно сделать что-то особенное (т.е. поместить это в анонимное пространство имен или объявить это static
). Таким образом, обычное использование встроенной функции уже демонстрирует внешнюю связь без необходимости использования ключевого слова extern
.
Как я думал, это должно работать:
//a.cpp
inline void f(int) {}
//b.cpp
extern void f(int);
int main() { f(4); }
Затем, прочитав this (" 1), оно должно быть объявлено inline
в каждой единице перевода. ").
Эта ссылка верна, но посмотрите немного больше там, где написано "Определение встроенной функции [...] должно присутствовать в единице перевода, где к ней осуществляется доступ [...]." Ваш пример имеет объявление f
в b.cpp
, но не определение. Если вы собираетесь звонить f
с b.cpp
, вам нужно полное определение в этой единице перевода, как в:
inline void f(int) {}
(Это тот же код, который существует в a.cpp
.) Если вы уберете фигурные скобки, то у вас есть объявление, но не определение, что делает незаконным вызов f
из этой единицы перевода.
По сути, очень сложно определить встроенную функцию вне заголовочного файла, если вы не зададите ей внутреннюю связь. Это связано с тем, что каждый исходный файл, использующий встроенную функцию, должен иметь свою собственную копию тела функции, а это означает, что если вы измените функцию, вы должны внести это изменение в несколько файлов. Уф. Не делай этого. Определите каждую из ваших inline
функций в заголовочном файле. Если вы считаете, что хотите определить его в исходном файле, вы, вероятно, неправильно поняли, что означает «inline
».
Что означает "inline
"?
Что касается компилятора, ключевое слово inline
ничего не значит (почти). Это просто флаг определения функции, который распространяется в объектный код, так что компоновщик видит его. Компилятор обрабатывает функцию так же, как и любую другую функцию. Функция может быть вызвана как обычно, или обращения к ней могут быть встроенными & ndash; как и любая другая функция.
Единственный случай, когда компилятор может что-то сделать с флагом inline
, - это когда функция объявлена inline
, используется, но не имеет определения. Это ошибка, которая может быть обнаружена до того, как линкер вступит во владение. Он не не должен быть пойман компилятором, но это может быть. (Если компилятор не перехватит его, он будет перехвачен компоновщиком.)
Переход к стадии связывания. Когда компоновщик видит флаг inline
, он приостанавливает действие правила одного определения для этой функции. Компоновщик ожидает увидеть определение функции в каждом модуле перевода, который все еще использует функцию после оптимизаций компилятора. Он может выбрать любое из этих определений в качестве окончательной реализации. Отсюда причина того, что все определения должны совпадать.
И это все. Ключевое слово inline
в основном означает, что определение функции находится в заголовочном файле. Он говорит компоновщику не жаловаться, когда это определение появляется в нескольких единицах перевода, потому что это ожидается.
Возвращаясь к вопросу, похоже, что целью было объявить функцию inline
, определение которой появилось бы только в одной единице перевода. Другими словами, функция будет помечена как определенная в нескольких единицах перевода, но определение будет только в одной. Вроде как несовместимо, если не прямо противоречиво.