Ошибка компоновщика C ++ - PullRequest
       12

Ошибка компоновщика C ++

0 голосов
/ 12 января 2009

У меня была такая функция, которой не было в классе:

// 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(){}
};

И взрыв! Исправлено.

Вопрос: ПОЧЕМУ?

Ответы [ 2 ]

13 голосов
/ 12 января 2009

Включение охраны только защищает эту функцию от включения в один и тот же модуль перевода дважды. Но это не защитит эту функцию от включения в целую программу дважды.

Поскольку функция не является встроенной, она нарушает правило единого определения, если она встречается более одного раза во всей программе. Сделайте его встроенным, чтобы решить проблему, или поместите определение в файл реализации, поместив только его объявление в заголовок.

// Gets the maximum number of tracks displayable. possible fix:
inline utils::uint32 GetConstMaxSystemRange() {
    return constMaxSystemNumber - constMinSystemNumber + 1;
}

На заметку - лучше не помещайте const во встроенное возвращаемое значение. Временные из них не могут быть квалифицированы как const / volatile. Но это также не обязательно: вы все равно не можете их изменить. Насколько я знаю, это игнорируется. Но это никогда не даст эффекта.

3 голосов
/ 12 января 2009

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

Для учеников существует другая политика, которая допускает дубликаты, которые впоследствии корректно обрабатываются компоновщиком.

Вы можете поместить его в безымянное пространство имен или добавить статический перед ним, чтобы он стал локальным для модуля перевода. Однако это не правильный способ исправить это - просто включите объявление в заголовок и поместите реализацию в файл, и все будет в порядке.

...