Объявить массив в заголовке C++ и определить его в файле cpp?
это, вероятно, очень простая вещь, но я новичок в C++, поэтому мне нужна помощь.
Я просто хочу объявить массив в моем заголовочном файле C++, например:
int lettersArr[26];
а затем определите его в функции в файле cpp, например:
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 };
но это не сработает.
у меня неправильный синтаксис или что-то еще? Каков правильный путь к этому?
Спасибо большое.
7 ответов
добавить extern
к объявлению в заголовочном файле.
extern int lettersArr[26];
(кроме того, если вы не планируете изменять массив, подумайте также о добавлении const
.)
определение должно иметь тип. Добавить int
(или const int
):
int lettersArr[26] = { letA, /*...*/ };
:
extern int lettersArr[];
источник в глобальной области:
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 lettersArr[26];
источник в функции:
int localLettersArr[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 };
memcpy (lettersArr, localLettersArr, sizeof (localLettersArr));
измените то, что у вас есть в заголовке на:
extern int lettersArr[26];
Так что это станет объявлением, а не определением.
другие описали, как инициализация массива может быть перемещена в файл реализации, который точно не отвечает на ваш вопрос, но является обходным путем, который полезно знать.
Я просто хочу объявить массив в моем заголовочном файле c++
если вы действительно хотите иметь массив все в файле заголовка, в том числе с инициализацией в файле заголовка, то вы можете
дать ему внутренняя перелинковка С помощью
static
илииспользовать локальные статические в встроенной функции (которая поддерживает эффективно внешнюю связь), или
немного шаблон трюк (также поддерживает внешние связи).
последние два решения являются обходными путями из-за отсутствия "inline
" данные на C++. То есть возможность определить тот же объект области пространства имен в более чем одна единица перевода. У вас есть это для функций, via 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;
}
локальная статика в inline функция
это, наверное, вообще "лучшее" решение, чтобы использовать, когда нет никаких весомых причин для выбора одного из других решений. Одна хорошая вещь заключается в том, что легко обеспечить динамическую инициализацию. Здесь я просто предположил, что вы никогда не будете хранить 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, Одно Правило Определения, делает специальное исключение для шаблонов:
#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;
}
Cheers & hth.,
Вы можете сделать это так:
в заголовке
extern int lettersArr[26];
in .cpp
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 };
вот фрагмент из одного из моих заголовочные файлы (реализация .файл cpp доступы массива): (Для доступа к массиву используйте dummy::messages вне пространства имен dummy.)
<pre>
namespace dummy {
const static string messages[] = {
"Unix does not echo the password field. Why do you think this is?",
"The firewall blocks external access to ouranos. You need to login to helios and ssh or sftp to ouranos",
"You need to experience of the command line. Not all systems have a gui.",
};
class Message {
public:
Message();
virtual ~Message();
string getMessage();
string getMessage( int index );
int getRandomNumber();
};
} /* namespace dummy */
</pre>