web-dev-qa-db-fra.com

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.

22
tree-hacker

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, /*...*/ };
22
aschepler

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));
4
user511089

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.

2
Kos

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, ou

  • utilisez 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.,

1

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 };
0
Vlad

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>
0
G O'Rilla