Déclarer un tableau dans un en-tête C++ et le définir dans un fichier cpp?
C’est probablement une chose très simple, mais je suis novice en C++, alors j’ai besoin d’aide.
Je veux juste déclarer un tableau dans mon fichier d'en-tête C++ comme:
int lettersArr[26];
puis définissez-le dans une fonction du fichier cpp telle que:
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 };
mais ça ne marche pas.
Ai-je la mauvaise syntaxe ou quelque chose? Quelle est la bonne façon de procéder?
Merci beaucoup.
Ajoutez extern
à la déclaration dans le fichier d'en-tête.
extern int lettersArr[26];
(En outre, si vous envisagez de modifier le tableau, envisagez également d'ajouter const
.)
La définition doit avoir un type. Ajouter int
(ou const int
):
int lettersArr[26] = { letA, /*...*/ };
Entête:
extern int lettersArr[];
Source au niveau mondial:
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 };
ou si vous voulez vraiment le faire dans une fonction:
Source à portée mondiale:
int lettersArr[26];
Source en fonction:
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));
Changez ce que vous avez dans l'en-tête en:
extern int lettersArr[26];
afin qu'il devienne une déclaration et non une définition.
D'autres ont décrit la manière dont l'initialisation du tableau peut être déplacée vers un fichier d'implémentation, ce qui ne répond pas exactement à votre question, mais constitue une solution de contournement qu'il est utile de connaître.
Je veux juste déclarer un tableau dans mon fichier d'en-tête C++
Si vous voulez vraiment avoir tout le tableau dans votre fichier d’en-tête, y compris l’initialisation dans votre fichier d’en-tête, vous pouvez alors:
donnez-lui lien interne} _ en utilisant
static
, ouutilisez un local static dans une fonction inline (qui supporte efficacement les liaisons externes),
utilisez un peu de astuce de modèle} _ (supporte également les liens externes).
Les deux dernières solutions sont des solutions de contournement pour le manque de données "inline
" en C++. C'est-à-dire la possibilité de définir le même objet de portée d'espace de noms dans plusieurs unités de traduction. Vous avez cela pour les fonctions, via inline
, mais malheureusement pas pour les objets: sans employer une solution de contournement, l'éditeur de liens ne fera que protester contre plusieurs définitions.
Lien interne
Ce n'est généralement pas une bonne solution. Il crée un tableau dans chaque unité de traduction où l'en-tête est inclus. Mais c'est préférable pour les objets const
relativement petits parce que c'est si 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;
}
Fonction statique locale inline
C'est probablement la "meilleure" solution à utiliser lorsqu'il n'y a pas de raison impérieuse de choisir l'une des autres solutions. Une bonne chose est qu’il est facile de fournir une initialisation dynamique. Ici, je viens de supposer que vous ne stockerez jamais 0 dans le tableau (ajoutez une logique de vérification supplémentaire si cette hypothèse ne tient pas):
#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;
}
Astuce de modèle
L'astuce de modèle fonctionne parce que la règle ODR, One de la norme, crée une exemption spéciale pour les modèles:
#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;
}
Vive & hth.,
Vous pouvez le faire de cette façon:
dans l'en-tête
extern int lettersArr[26];
en .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 };
Voici un extrait d'un de mes fichiers d'en-tête (le fichier d'implémentation .cpp accède au tableau):
<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>