This is probably a really simple thing but I\'m new to C++ so need help.
I just want to declare an array in my C++ header file like:
int lettersArr[2
try:
lettersArr = { 1, 2, 3, 4 }
Here's a snippet from one of my header files (the implementation .cpp file accesses the array): (Use dummy::messages outside of the dummy namespace to access the array.)
<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>
Add extern
to the declaration in the header file.
extern int lettersArr[26];
(Also, unless you plan to change the array, consider also adding const
.)
The definition must have a type. Add int
(or const int
):
int lettersArr[26] = { letA, /*...*/ };
Change what you have in the header to:
extern int lettersArr[26];
so that it will become a declaration, not a definition.
Other have described how the array initialization can be moved to an implementation file, which is not exactly answering your question, but is a workaround that's useful to know.
I just want to declare an array in my C++ header file
If you really want to have the array all in your header file, including having the initialization in your header file, then you can
give it internal linkage by using static
, or
use a local static in an inline function (which supports effectively external linkage), or
use a little template trick (also supports external linkage).
The last two solutions are workarounds for the lack of "inline
" data in C++. That is, the ability to define the same namespace scope object in more than one translation unit. You have that for functions, via inline
, but unfortunately not for objects: without employing some workaround the linker will just protest about multiple definitions.
This is generally not a good solution. It creates one array in each translation unit where the header is included. But it's preferable for relatively small const
objects because it's so simple:
#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;
}
This is probably the generally "best" solution, to use when there is no overriding reason for choosing one of the other solutions. One nice thing is that it's easy to provide dynamic initialization. Here I've just assumed that you will never store 0 in the array (add some extra checking logic if that assumption doesn't hold):
#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;
}
The template trick works because the standard's ODR, One Definition Rule, makes a special exemption for templates:
#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.,
Header:
extern int lettersArr[];
Source at the global scope:
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 };
or if you really want to do it in a function:
Source at global scope:
int lettersArr[26];
Source in function:
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));