Другие описали, как инициализация массива может быть перемещена в файл реализации, который не совсем отвечает на ваш вопрос, но это обходной путь, который полезно знать.
Я просто хочу объявить массив в моем заголовочном файле C ++
Если вы действительно хотите иметь весь массив в вашем заголовочном файле, включая инициализацию в вашем заголовочном файле, тогда вы можете
дать ему внутреннюю связь с помощью static
или
использовать локальную статическую во встроенной функции (которая эффективно поддерживает внешнюю связь) или
используйте небольшой шаблонный трюк (также поддерживает внешнюю связь).
Последние два решения - обходные пути для отсутствия данных "inline
" в C ++. То есть возможность определять один и тот же объект области пространства имен в нескольких единицах перевода. У вас это есть для функций через inline
, но, к сожалению, не для объектов: без использования обходного пути компоновщик будет просто протестовать против нескольких определений.
Внутренняя связь
Как правило, это не очень хорошее решение. Он создает один массив в каждой единице перевода, в которую включен заголовок. Но это предпочтительно для относительно небольших const
объектов, потому что это так просто:
#include <stddef.h>
#include <iostream>
int const letA = 'A';
int const letB = 'B';
int const letC = 'C';
int const letD = 'D';
int const letE = 'E';
int const letF = 'F';
int const letG = 'G';
int const letH = 'H';
int const letI = 'I';
int const letJ = 'J';
int const letK = 'K';
int const letL = 'L';
int const letM = 'M';
int const letN = 'N';
int const letO = 'O';
int const letP = 'P';
int const letQ = 'Q';
int const letR = 'R';
int const letS = 'S';
int const letT = 'T';
int const letU = 'U';
int const letV = 'V';
int const letW = 'W';
int const letX = 'X';
int const letY = 'Y';
int const letZ = 'Z';
static int lettersArr[26] =
{
letA, letB, letC, letD, letE, letF, letG, letH,
letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
letT, letU, letV, letW, letX, letY, letZ
};
int main()
{
using namespace std;
for( int i = 0; i < 26; ++i )
{
cout << char( lettersArr[i] );
}
cout << endl;
}
Локальная статика во встроенной функции
Это, пожалуй, обычно «лучшее» решение, которое следует использовать, когда нет основополагающей причины выбора одного из других решений. Одна приятная вещь заключается в том, что легко обеспечить динамическую инициализацию. Здесь я просто предположил, что вы никогда не будете хранить 0 в массиве (добавьте дополнительную логику проверки, если это предположение не выполняется):
#include <stddef.h>
#include <iostream>
template< class Type, int n >
int countOf( Type (&)[n] ) { return n; }
typedef int LettersArray[26];
inline LettersArray& lettersArrayRef()
{
static LettersArray theArray;
if( theArray[0] == 0 )
{
// Assuming normal ASCII-based character set with contiguous alpha.
for( int i = 0; i < countOf( theArray ); ++i )
{
theArray[i] = i + 'A';
}
}
return theArray;
}
static LettersArray& lettersArr = lettersArrayRef();
int main()
{
using namespace std;
for( int i = 0; i < 26; ++i )
{
cout << char( lettersArr[i] );
}
cout << endl;
}
Шаблон трюка
Уловка шаблона работает потому, что стандартное ODR , One Definition Rule делает специальное исключение для шаблонов:
#include <stddef.h>
#include <iostream>
int const letA = 'A';
int const letB = 'B';
int const letC = 'C';
int const letD = 'D';
int const letE = 'E';
int const letF = 'F';
int const letG = 'G';
int const letH = 'H';
int const letI = 'I';
int const letJ = 'J';
int const letK = 'K';
int const letL = 'L';
int const letM = 'M';
int const letN = 'N';
int const letO = 'O';
int const letP = 'P';
int const letQ = 'Q';
int const letR = 'R';
int const letS = 'S';
int const letT = 'T';
int const letU = 'U';
int const letV = 'V';
int const letW = 'W';
int const letX = 'X';
int const letY = 'Y';
int const letZ = 'Z';
template< class Dummy >
struct Letters_
{
static int array[26];
};
template< class Dummy >
int Letters_< Dummy >::array[26] =
{
letA, letB, letC, letD, letE, letF, letG, letH,
letI, letJ, letK, letL, letM, letN, letO, letP, letQ, letR, letS,
letT, letU, letV, letW, letX, letY, letZ
};
static int (&lettersArr)[26] = Letters_<void>::array;
int main()
{
using namespace std;
for( int i = 0; i < 26; ++i )
{
cout << char( lettersArr[i] );
}
cout << endl;
}
Приветствия и hth.,