По какой-то причине ни один из ответов до сих пор не удосужился объяснить разницу между вашим целочисленным NUM_SOCIODEM_FILES
объектом и массивом SOCIODEM_FILENAMES
объектом.Последний вызывает ошибку компоновщика по уже объясненным причинам: потому что вы включаете заголовочный файл в несколько файлов реализации.Тем не менее, первое связывалось бы без каких-либо проблем (потому что действительно нет проблем с объявлением NUM_SOCIODEM_FILES
).Почему?
Причина этого в том, что ваш NUM_SOCIODEM_FILES
объект объявлен const
.В C ++ const объекты по умолчанию имеют внутреннюю связь , что означает, что они не вызывают проблем со связыванием, даже если они определены в нескольких файлах реализации.Другими словами, в C ++ ваш NUM_SOCIODEM_FILES
эквивалентен
static const int NUM_SOCIODEM_FILES = 5; /* internal linkage */
, поэтому он не приводит к проблемам со связыванием.
В то же время ваш SOCIODEM_FILENAMES
не являетсяобъявленная константа, поэтому по умолчанию она получает внешнюю связь и в конечном итоге приводит к ошибкам компоновщика.Но если вы также объявите свой SOCIODEM_FILENAMES
как const
, проблема исчезнет
const char * const SOCIODEM_FILENAMES[ NUM_SOCIODEM_FILES ] = {
...
Обратите внимание, где в объявлении помещается дополнительный const
.Если вы просто добавите этот дополнительный const
и оставите все остальное как есть (т.е. сохраните определение, если SOCIODEM_FILENAMES
в заголовочном файле), компоновщик не сообщит об ошибке, даже если вы включите свой заголовочный файл в несколько блоков перевода.
Это не рекомендуемый подход, так как таким образом вы дадите свою внутреннюю связь SOCIODEM_FILENAMES
и получите автономную копию массива SOCIODEM_FILENAMES
в каждой единице перевода - что-то, что может работать нормально, но все же делаеточень мало смысла.Поэтому для вашего массива обычно лучше использовать подход extern
, рекомендованный в других ответах.
Однако учтите, что обычно вы не должны делать это для объявления NUM_SOCIODEM_FILES
!!!Это нормально, как это определено в заголовочном файле.Если вы не пытаетесь сделать что-то необычное, скалярные константы обычно должны быть определены как с инициализатором в заголовочных файлах - таким образом, их можно рассматривать как константы времени компиляции во всех единицах перевода, что довольно ценноиметь.Итак, остерегайтесь странного совета, присутствующего в некоторых других ответах, чтобы перенести определение NUM_SOCIODEM_FILES
в .cpp
файл - это на самом деле не имеет никакого смысла и является абсолютно неправильной вещью.