Почему ошибка LINK2005: объект уже определенный ошибка исчезает, когда я объявляю объект как статический - PullRequest
3 голосов
/ 15 ноября 2010

У меня есть следующая структура и объект структуры, определенные в заголовочном файле, как показано ниже:

struct STConfigurationDetails
{
    bool bAutoStart;
    bool bAutoLog;
    bool bAutoScan;
    bool bAutoMount;
    bool bAutoOpen;
    bool bAutoDetectLast;
};

struct STConfigurationDetails g_objConfigurationDetails ;

В самом заголовочном файле у меня есть и метод, и тело метода, которое использует g_objConfigurationDetails. Это прекрасно работает, когда я включаю заголовочный файл в другой файл cpp и вызываю метод. Но в тот момент, когда я добавил заголовочный файл в другой файл cpp, я получил ошибку:

Ошибка 1 ошибка LNK2005: «struct STConfigurationDetails g_objConfigurationDetails» (? G_objConfigurationDetails @@ 3USTConfigurationDetails @@ A) уже определена в NDSClientDlg.obj NDSConnectDlg.obj NDSClient * 1007

Ошибка 2: фатальная ошибка LNK1169: найден один или несколько кратно определенных символов d: \ FromClearCase \ Development_view \ NDS_11152010 \ exe \ Debug \ NDSClient.exe 1 NDSClient

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

Это потому, что в моем заголовочном файле есть глобальная переменная, и он включен в несколько CPP?

Ответы [ 3 ]

4 голосов
/ 15 ноября 2010

Добавление static может решить вашу проблему с линковкой, но даст вам гораздо большую проблему. Эта переменная больше не является глобальной и имеет разные значения в каждом CPP-файле, который ее использует. Вам нужно объявить его как extern в заголовочном файле, а затем объявить его еще раз в одном файле CPP как есть.

Когда вы используете static, это означает, что переменная будет полностью локальной для текущего файла CPP и не будет доступна другим файлам. Вот почему компоновщик больше не заботится о наличии другой статической переменной в другом файле с таким же именем. Это не одна и та же переменная.

Если вы хотите действительно глобальную переменную, она должна быть объявлена ​​ровно в одном файле CPP, и только ее прототип (с extern) должен находиться в заголовочном файле, который будет использоваться совместно с другими файлами CPP. Это в точности как функции - объявлено в одном файле, прототип для остальных. Для функций вы просто не предоставляете тело. Для переменных вы используете extern.

3 голосов
/ 15 ноября 2010

Это довольно легко, если вы тщательно об этом думаете. Переменная определяется в заголовке, поэтому каждый файл .cpp, содержащий этот заголовок, получает свою собственную копию переменной. Теперь, если вы не добавите static, все файлы .cpp получат одну и ту же переменную с внешней связью, и во время компиляции произойдет ошибка.

Когда вы добавляете static, каждый .cpp по-прежнему имеет свою переменную, не связанную с другими переменными из того же определения, но у них больше нет внешней связи, поэтому компоновщик не выдает ошибку.

Однако не забывайте, что каждая переменная - это отдельная переменная, которая занимает память и имеет накладные расходы на создание / уничтожение, и вы получите непредвиденное поведение, если ваш код ожидает, что для всех файлов .cpp будет использоваться только одна переменная.

0 голосов
/ 15 ноября 2010

Глобальные статические переменные имеют внутреннюю связь .

...