74 votes

initialiser un tableau const dans un initialiseur de classe en C ++

J'ai la classe suivante en C++:

class a {
    const int b[2];
    // other stuff follows

    // and here's the constructor
    a(void);
}

La question est, comment puis-je initialiser b dans la liste d'initialisation, étant donné que je ne peux pas l'initialiser à l'intérieur du corps de la fonction du constructeur, car b est - const?

Cela ne fonctionne pas:

a::a(void) : 
    b([2,3])
{
     // other initialization stuff
}

Edit: le cas de Le dire c'est quand je peux avoir des valeurs différentes pour b pour les diverses instances, mais les valeurs sont connus pour être constante pendant toute la durée de l'instance.

72voto

Flexo Points 39273

Avec C ++11, la réponse à cette question a maintenant changé et vous pouvez en fait:

 struct a {
    const int b[2];
    // other bits follow

    // and here's the constructor
    a();
};

a::a() :
    b{2,3}
{
     // other constructor work
}

int main() {
 a a;
}
 

32voto

pongba Points 552

Comme les autres l'ont dit, ISO C ++ ne prend pas cela en charge. Mais vous pouvez contourner le problème. Utilisez simplement std :: vector à la place.

 int* a = new int[N];
// fill a

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};
 

25voto

Luc Touraille Points 29252

Ce n'est pas possible dans la norme actuelle. Je pense que vous pourrez le faire en C ++ 0x en utilisant des listes d’initialisation (voir Un bref aperçu de C ++ 0x , par Bjarne Stroustrup, pour plus d’informations sur les listes d’initialisation et d’autres fonctionnalités intéressantes de C ++ 0x).

12voto

Matthew Points 91

std::vector utilise le tas. Waow, quel gâchis ce serait juste pour le plaisir d'un const santé mentale-case. Le point de std::vector est une dynamique de croissance au moment de l'exécution, et non pas un vieux de la vérification de syntaxe qui doit être fait au moment de la compilation. Si vous n'allez pas à grandir alors créer une classe pour envelopper un tableau normal.

#include <stdio.h>


template <class Type, size_t MaxLength>
class ConstFixedSizeArrayFiller {
private:
    size_t length;

public:
    ConstFixedSizeArrayFiller() : length(0) {
    }

    virtual ~ConstFixedSizeArrayFiller() {
    }

    virtual void Fill(Type *array) = 0;

protected:
    void add_element(Type *array, const Type & element)
    {
        if(length >= MaxLength) {
            // todo: throw more appropriate out-of-bounds exception
            throw 0;
        }
        array[length] = element;
        length++;
    }
};


template <class Type, size_t Length>
class ConstFixedSizeArray {
private:
    Type array[Length];

public:
    explicit ConstFixedSizeArray(
        ConstFixedSizeArrayFiller<Type, Length> & filler
    ) {
        filler.Fill(array);
    }

    const Type *Array() const {
        return array;
    }

    size_t ArrayLength() const {
        return Length;
    }
};


class a {
private:
    class b_filler : public ConstFixedSizeArrayFiller<int, 2> {
    public:
        virtual ~b_filler() {
        }

        virtual void Fill(int *array) {
            add_element(array, 87);
            add_element(array, 96);
        }
    };

    const ConstFixedSizeArray<int, 2> b;

public:
    a(void) : b(b_filler()) {
    }

    void print_items() {
        size_t i;
        for(i = 0; i < b.ArrayLength(); i++)
        {
            printf("%d\n", b.Array()[i]);
        }
    }
};


int main()
{
    a x;
    x.print_items();
    return 0;
}

ConstFixedSizeArrayFiller et ConstFixedSizeArray sont réutilisables.

La première permet d'exécution de la vérification de limites lors de l'initialisation de la matrice (même comme un vector), qui peut devenir plus tard l' const après cette initialisation.

Le second permet la matrice soit allouée à l'intérieur d'un autre objet, qui pourrait être sur le tas ou tout simplement la pile si c'est l'emplacement de l'objet. Il n'y a pas de perte de temps de l'allocation dans le tas. Il effectue également au moment de la compilation const vérifier sur le tableau.

b_filler , c'est un petit cours privé pour fournir les valeurs d'initialisation. La taille de la matrice est vérifié au moment de la compilation avec les arguments de modèle, donc il n'y a aucune chance de sortir des limites du terrain.

Je suis sûr qu'il y a de plus exotique des moyens de modifier cette. C'est un premier coup de couteau. Je pense que vous pouvez très bien faire pour tout le compilateur de la lacune de classes.

9voto

orj Points 4480

La norme ISO C++ ne pas vous laisser faire cela. Si il l'a fait, la syntaxe serait probablement:

a::a(void) :
b({2,3})
{
    // other initialization stuff
}

Ou quelque chose le long de ces lignes. À partir de votre question, il sonne comme ce que vous voulez est une constante de la classe (aka statique) membre de la matrice. C++ ne permettent de le faire. Comme suit:

#include <iostream>

class A 
{
public:
    A();
    static const int a[2];
};

const int A::a[2] = {0, 1};

A::A()
{
}

int main (int argc, char * const argv[]) 
{
    std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "\n";
    return 0;
}

De la sortie:

A::a => 0, 1

Maintenant, bien sûr, puisque c'est un membre de classe statique, il est le même pour chaque instance de la classe A. Si ce n'est pas ce que vous voulez, c'est à dire que vous souhaitez que chaque instance d'Un avoir différentes valeurs d'élément dans le tableau a, puis vous faites l'erreur d'essayer de faire le tableau const pour commencer. Vous devez simplement faire ceci:

#include <iostream>

class A 
{
public:
    A();
    int a[2];
};

A::A()
{
    a[0] = 9; // or some calculation
    a[1] = 10; // or some calculation
}

int main (int argc, char * const argv[]) 
{
    A v;
    std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "\n";
    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X