Встроенная функция связи

Я не могу понять следующее поведение: один заголовок с некоторыми базовыми типами и другой заголовок, в котором я использую эти типы в нескольких функциях. После этого я начал создавать классы на основе определенных типов и функций. В заголовке функции, если я оставляю следующую подпись:

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 → , чтобы избежать множественного включения. - Не используйте косвенное включение: если вы используете тип в файле, добавьте соответствующий заголовок, даже если в него входит другой заголовок в том же файле.