Встроенная функция связи
Я не могу понять следующее поведение: один заголовок с некоторыми базовыми типами и другой заголовок, в котором я использую эти типы в нескольких функциях. После этого я начал создавать классы на основе определенных типов и функций. В заголовке функции, если я оставляю следующую подпись:
void whateverFunction(parameters)
Компонент указывает, что существует множество определений anyFunction. Теперь, если изменить его на:
inline void whateverFunction(parameters)
проблема связи пропала, и все компилирует и хорошо связывает. То, что я знаю относительно встроенного, заключается в том, что он заменяет любой вызов функции кодом, отличным от того, что он довольно темный, поэтому мой вопрос:
Как компоновщик рассматривает встроенные функции в С++?
Ответы
Ответ 1
Если функция в заголовке не является встроенной, то несколько определений этой функции (например, в нескольких единицах перевода) являются нарушением правил ODR.
Встроенные функции по умолчанию имеют внешнюю связь. Следовательно, как следствие правил ODR (приведенных ниже), такие множественные определения (например, в нескольких единицах перевода) - это Okay:
$3.2/5- "Может быть больше одного определение типа класса (п. 9), тип перечисления (7.2), inline функция с внешней связью(7.1.2), шаблон класса (пункт 14), нестатический шаблон функции (14.5.6), статический элемент данных шаблона класса (14.5.1.3), функция-член класса шаблон (14.5.1.1) или шаблон специализация, для которой какой-то шаблон параметры не указаны (14.7, 14.5.5) в программе, при условии, что каждое определение появляется в другом перевода, а также определения удовлетворяют следующему требования. Учитывая такой объект названный D, определяемый более чем одним единицы перевода, затем
- каждое определение D состоит одной и той же последовательности токенов; и [...]
Как компоновщик рассматривает встроенные функции, это довольно подробная информация о уровне реализации. Достаточно знать, что реализация допускает такие разборчивые ошибки в рамках ограничений правил ODR.
Обратите внимание, что если декларация функции в заголовке изменяется на "static inline....", то встроенная функция явно имеет внутреннюю привязку, и каждая единица перевода имеет свою собственную копию статической встроенной функции.
Ответ 2
Компонент может вообще не видеть встроенные функции. Они обычно скомпилированы прямо в код, который их вызывает (т.е. Вместо вызова функции используется код).
Если компилятор не хочет встроить функцию (поскольку это всего лишь подсказка), я не уверен, но я думаю, что компилятор испускает ее как обычную не-встроенную функцию и как-то комментирует ее, поэтому компоновщик просто выбирает первый экземпляр, который он видит, и игнорирует остальные.
Ответ 3
Inline просто маскирует проблему. Наличие нескольких определений указывает на проблему где-то.
Просто будьте осторожны, как вы используете свои заголовки. Не забывайте:
- < #ifndef HEADER_NAME
/#define HEADER_NAME
/#endif
→ , чтобы избежать множественного включения.
- Не используйте косвенное включение: если вы используете тип в файле, добавьте соответствующий заголовок, даже если в него входит другой заголовок в том же файле.