Я перебирал эту статью, и она рассказывает о процессе компиляции (предварительный процесс, компиляция, ссылка). Я понимаю, что включение охранников просто решает проблему предотвращения множественных включений в одной и той же единице перевода. Поэтому, если у меня есть следующий сценарий:
File : Common.h
----------------
#ifndef External_Header
#include "iostream"
#define External_Header
std::string R = "dsds";
#endif
Теперь у меня есть два файла cpp, оба из которых включают этот заголовочный файл. Я понимаю, почему я получаю ошибку компоновщика "fatal error LNK1169: one or more multiply defined symbols found".
Мне интересно, почему я не получаю такую же ошибку компоновщика, когда я определяю структуру вместо строки.
Любые мысли или идеи, которые могли бы прояснить это.
File : Common.h
----------------
#ifndef External_Header
#include "iostream"
#define External_Header
struct mystruct
{
int a;
};
#endif
Проблема может заключаться в том, что вы создаете переменную в одном случае, но в другом случае определяете новый тип. Чтобы проверить это, вы можете попробовать следующий код.
struct mystruct
{
int a;
} myTestVar;
Это потому, что struct
не являются символами.
Стандарт C++ явно позволяет нам переопределять типы в разных единицах перевода... пока их определение не изменится.
[C++11: 3.2/1]:
ни одна единица перевода не должна содержать более одного определения любой переменной, функции, типа класса, типа перечисления или шаблона.
[C++11: 3.2/3]:
каждая программа должна содержать ровно одно определение каждой не-встроенной функции или переменной, которая используется в этой программе odr; не требуется диагностика. [..]
Обратите внимание, как типы упоминаются в прежнем правиле, но не в последнем. Это делается немного позже:
[C++11: 3.2/5]:
может быть несколько определений типа класса [..], при условии, что каждое определение отображается в другой единицы перевода и при условии, что определения удовлетворяют следующим требованиям. Учитывая такой объект с именемD
определенный более чем в одной единицы перевода, тогда
- каждое определение
D
должно состоять из одной и той же последовательности токенов;- [..]
Программирование с перекрестными переводами было бы невозможно, если бы не это различие.
myvar;
после закрытия фигурного определения структуры, и у вас снова будет ошибка дублированного символа. Ошибка компоновщика, которую вы получаете в первом случае, связана с тем, что идентичные символы объявляются в нескольких единицах перевода, и компоновщик не имеет ни малейшего представления, что выбрать для глобального разрешения.