У меня была такая функция, которой не было в классе:
// Gets the maximum number of tracks displayable
const utils::uint32 GetConstMaxSystemRange()
{
return constMaxSystemNumber - constMinSystemNumber + 1;
}
Он отлично компилировался в VS2005, но потом я получал ошибки компоновщика для каждого файла после первого, который его включил, хотя я использовал Compile Guards. Я догадывался, что окружил его таким классом:
class CDSLimitsAccess
{
public:
// Gets the maximum number of tracks displayable
static const utils::uint32 GetConstMaxSystemRange()
{
return constMaxSystemNumber - constMinSystemNumber + 1;
}
protected:
CDSLimitsAccess(){}
};
И бац! Фиксированный.
Вопрос: ПОЧЕМУ?





Включить охранники только защищают эту функцию от включения в одну и ту же единицу перевода дважды. Но это не защитит эту функцию от повторного включения во всю программу.
Поскольку функция не является встроенной, она нарушает правило одного определения, если встречается более одного раза во всей программе. Сделайте его встроенным, чтобы решить проблему, или поместите определение в файл реализации, поместив только его объявление в заголовок.
// Gets the maximum number of tracks displayable. possible fix:
inline utils::uint32 GetConstMaxSystemRange() {
return constMaxSystemNumber - constMinSystemNumber + 1;
}
Кстати, лучше не ставить const во встроенное возвращаемое значение. Их временные элементы не могут быть определены с помощью const / volatile. Но это тоже не обязательно: вы все равно не можете их изменить. Насколько я знаю, это игнорируется. Но это никогда не подействует.
да, зависит ли компилятор от встроенных вызовов функций. объявление функции встроенной делает функцию встроенной функцией. независимо от того, действительно ли вызовы к нему встроены, правила о встроенных функциях, относящиеся к ODR, по-прежнему остаются в силе.
обратите внимание, что если вы поместите функцию в свой файл реализации (что я рекомендую, если ваша функция больше или может зависеть от имен, которые вы не можете или не хотите отображать в заголовке), вам необходимо удалить встроенный спецификатор.
Потому что, если это свободно плавающая функция, при каждом включении она будет скомпилирована в файл .obj, а когда дело доходит до связывания, есть дубликаты.
Для членов класса существует другая политика, которая допускает дублирование, которое позже обрабатывается компоновщиком должным образом.
Вы можете поместить его в безымянное пространство имен или добавить статический объект перед ним, чтобы он стал локальным для единицы перевода. Однако это неправильный способ исправить это - просто включите объявление в заголовок и поместите реализацию в файл, и все будет в порядке.
Я получаю новую ошибку компоновщика при компиляции с определением вне заголовка, так как что-то ниже по списку не может его найти. Встраивание (которое я должен был сделать в любом случае) исправил его. Спасибо! Однако не является ли встраивание частично решением компилятора и, следовательно, потенциально ненадежным в качестве решения?