IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

initialisation automatique d'un tableau membre d'une classe


Sujet :

Langage C++

  1. #1
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut initialisation automatique d'un tableau membre d'une classe
    Bonjour,

    Dans un programme, on peut définir un tableau lors de sa déclaration. Ex:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    unsigned char tab[] = {1, 2, 8, 11};
    Quel est le moyen le plus simple pour définir ce tableau s'il est membre d'une classe? On peut évidemment définir un à un les éléments du tableau dans le constructeur, ou définir un tableau local dans le constructeur et le recopier dans le tableau membre, mais j'aurais voulu savoir s'il existait un moyen de le définir en une seule opération.

    Merci.

  2. #2
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Bonjour

    Sans trop prendre de risque, je peux dire : dans la liste d'initialisation du constructeur.
    Depuis C++11, tu peux initialiser directement les données membres lors de la déclaration.
    Pour les tableaux qui ont une taille qui varie, tu peux utiliser std::vector. Si la taille est connue à la compilation, depuis C++11, std::array existe.

  3. #3
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Tout d'abord, merci pour ta réponse.
    Sans trop prendre de risque, je peux dire : dans la liste d'initialisation du constructeur.
    Je ne vois pas trop comment se servir de la liste initialisation dans ce cas. Par exemple, une classe que je vais appeler test.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class test{
    public:
    	test(void);
    	int tab[4];
    };
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "test.h"
     
    test::test(void):tab(je mets quoi ici?)
    {
    }
    Que dois-je mettre dans cette liste pour que le contenu du tableau soit 1, 8 , 6 , 2 par exemple?
    Malheureusement, je travaille avec VS2013 et son compilateur ne le permet pas, car j'obtiens le message suivant:
    impossible de spécifier un initialiseur explicite pour les tableaux
    Pour les tableaux qui ont une taille qui varie, tu peux utiliser std::vector. Si la taille est connue à la compilation
    Ca n'est pas très pratique dans mon cas car mes tableaux me servent à composer des trames de longueur connues. La classe gérant le port de transmission possède des méthodes attendant des tableaux "classiques" d'octets.

  4. #4
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    J'ai lu que VS2013 supportait beaucoup de fonctionnalités de C++11 (mais pas toutes). ll faut peut être l'activer quelque part dans les options.
    Tu peux essayer ce code C++11 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <iostream>
     
     
    class test
    {
    private:
    	static constexpr std::size_t m_size = 4;
     
    public:
    	int tab[m_size] = { 0, 1, 2, 3 };
     
    	test() { }
     
    	std::size_t size() const { return m_size; }
    };
     
    int main()
    {
    	test t;
    	for (std::size_t i = 0; i < t.size(); ++i)
    	{
    		std::cout << t.tab[i] << std::endl;
    	}
     
    	return 0;
    }
    Pour C++03, tu peux utiliser boost::array et faire une fonction qui retourne un tableau construit comme tu veux (pour l'appeler dans la liste d'initialisation en utilisant le constructeur par copie de boost::array) ; ou faire ta propre implémentation afin d'avoir un constructeur à utiliser dans la liste d'initialisation.

  5. #5
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    D'après microsoft, VS2013 supporte l'initialisation de membres non statiques.
    Je suis également allé voir dans les propriétés du projet, et en particulier la partie compilateur, si on pouvait paramétrer la version de la norme utilisée. Apparemment non.

    Le code que tu m'as fourni ne compile pas. La 1ère erreur générée est "Erreur 1 error C2143: erreur de syntaxe : absence de ';' avant 'size_t' ". A mon avis constepr n'est pas reconnu.

  6. #6
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Si c'est constexpr qui bloque, essaye ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <iostream>
     
     
    class test
    {
    public:
    	int tab[4] = { 0, 1, 2, 3 };
     
    	std::size_t size() const { return sizeof(tab) / sizeof(tab[0]); }
    };
     
    int main()
    {
    	test t;
    	for (std::size_t i = 0; i < t.size(); ++i)
    	{
    		std::cout << t.tab[i] << std::endl;
    	}
     
    	return 0;
    }

  7. #7
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Je retrouve l'erreur de départ pointant sur la définition du tableau
    Erreur 1 error C2536: 'test::test::tab' : impossible de spécifier un initialiseur explicite pour les tableaux

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par jackk Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include "test.h"
     
    test::test(void):tab(je mets quoi ici?)
    {
    }


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    #include<cstring>
    #include<iostream>
     
     
    template<size_t size>
    class Test {
    public:
     
        friend std::ostream& operator << (std::ostream& os, Test& a) {
            if ((a.nb_elements > 0) && (a.int_array != NULL)) {
                os << "[" << a.int_array[0];
     
                for(size_t nb = 1; nb < a.nb_elements; ++nb) {
                    os << ", " << a.int_array[nb];
                }
     
                os << "]";
            }
     
            return os;
        }
     
     
    public:
     
        Test() : int_array( ((size != 0)? new int[size]: NULL) ), nb_elements(size) {
            if (int_array != NULL) {
                std::memset(int_array, 0, size);
            }
        }
     
        ~Test() {
            if (int_array != NULL) {
                delete[] int_array;
                int_array = NULL;
            }
        }
     
     
    private: // or public:
        int* int_array;
        size_t nb_elements;
    };
     
    // ...
     
    Test<5> a;
    Test<6> b;
    std::cout << a << std::endl << b << std::endl

  9. #9
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Soit tu n'as pas activé C++11. Soit VS2013 est moisi... (troll)

    Cela dit, si tu peux avoir C++11 Tu peux utiliser std::array (?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <iostream>
    #include <array>
     
     
    class test
    {
    public:
    	std::array<int, 4> tab;
     
    	test() : tab({ 0, 1, 2, 3 }) { }
    	// Si la liste d'initialisation est mal gérée (code non équivalent) : test() { tab = { 0, 1, 2, 3 }; }
    };
     
    int main()
    {
    	test t;
    	for (std::size_t i = 0; i < t.tab.size(); ++i)
    	{
    		std::cout << t.tab[i] << std::endl;
    	}
     
    	return 0;
    }
    L'avantage c'est que si C++11 n'est pas activer on aura une erreur sur std::array.
    Sinon, il te reste plus qu'à utiliser boost::array ou faire ta propre implémentation.

    Edit :
    @foetus, je ne vois pas l'intérêt de ton code et encore moins l'utilisation de new [] et delete [] ici...

  10. #10
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Citation Envoyé par foetus Voir le message
    Je rappelle que l'on me proposait d'utiliser une liste d'initialisation dont je ne savais effectivement pas trop quoi faire.

    Pour le reste, je ne vois pas en quoi le code que tu me propose apporte une solution à mon proplème qui est de définir un tableau la déclaration de la classe.

  11. #11
    Membre éclairé
    Homme Profil pro
    Enseignant
    Inscrit en
    Juin 2004
    Messages
    516
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Juin 2004
    Messages : 516
    Points : 706
    Points
    706
    Par défaut
    Ca passe avec std::array .

    Pour les méthodes des classes qui attendent des tableaux classiques, je devrais pouvoir m'en sortir avec std::array;;data()

    Merci pour tout

  12. #12
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Edit :
    @foetus, je ne vois pas l'intérêt de ton code et encore moins l'utilisation de new [] et delete [] ici...
    Si pour me mettre des -1, VIVE LE C++11 et il n'existe que le C++11


    Citation Envoyé par jackk Voir le message
    Je rappelle que l'on me proposait d'utiliser une liste d'initialisation dont je ne savais effectivement pas trop quoi faire.

    Pour le reste, je ne vois pas en quoi le code que tu me propose apporte une solution à mon problème qui est de définir un tableau la déclaration de la classe.
    Tu peux avoir un attribut étant un tableau crochet
    Mais c'est tout sauf flexible: tableau fixe, il faut connaître la taille (la mettre en attribut), faire attention si c'est un tableau de pointeurs et ... des recopies de partout (pour l'initialisation, pour la recopie, pour l'affectation, ...)
    Sans parler du fait que tu ne peux pas faire d'initialisations paresseuses: là tu as 5 entiers, cela va encore

    Je te propose un pointeur avec une classe templatée, limite smart pointeur: cela améliore un peu les choses.

    Ce n'est pas par rien que Ehonn s'époumone avec ces std::vector, std::array, ces listes {} C++11 voire même en passant par boost: c'te machine de guerre
    Ehonn ne t'as parlé des reserve et des std::swap

  13. #13
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par foetus Voir le message
    Si pour me mettre des -1, VIVE LE C++11 et il n'existe que le C++11
    std::vector existe en C++98 (et oui, en 2014 (bientôt 2015), utiliser C++11 (qui supporté par la majorité des compilateurs) n'est pas absurde)

    Citation Envoyé par foetus Voir le message
    Tu peux avoir un attribut étant un tableau crochet
    Mais c'est tout sauf flexible: tableau fixe, il faut connaître la taille (la mettre en attribut), faire attention si c'est un tableau de pointeurs et ... des recopies de partout (pour l'initialisation, pour la recopie, pour l'affectation, ...)
    Sans parler du fait que tu ne peux pas faire d'initialisations paresseuses: là tu as 5 entiers, cela va encore

    Je te propose un pointeur avec une classe templatée, limite smart pointeur: cela améliore un peu les choses.

    Ce n'est pas par rien que Ehonn s'époumone avec ces std::vector, std::array, ces listes {} C++11 voire même en passant par boost: c'te machine de guerre
    Ehonn ne t'as parlé des reserve et des std::swap
    Mon code est simple et respecte la norme de C++11.
    Ton code est beaucoup trop compliqué et beaucoup trop dangereux et ne répond pas au problème de base : pouvoir initialiser un tableau qui ait une donnée membre en tapant 1, 2, 8, 11 (ce qui n'est pas possible en une seule ligne avec la std de C++03).

  14. #14
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    pouvoir initialiser un tableau qui ait une donnée membre en tapant 1, 2, 8, 11 (ce qui n'est pas possible en une seule ligne avec la std de C++03).
    Même avec les variadic function

    Ou alors en fonction des besoins (si la taille est inférieure à 10), tu peux préparer 10 templates (comme je l'ai fait en passant la taille) avec un constructeur ayant autant d'entiers que la taille

    Du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    template<1>
    class Test { Test(int a) { .... } int tab[1]; };
     
    template<2>
    class Test { Test(int a, int b) { .... } int tab[2]; };
     
    template<3>
    class Test { Test(int a, int b, int c) { .... } int tab[3]; };
     
    template<4>
    class Test { Test(int a, int b, int c, int d) { .... } int tab[4]; };
     
    /* ... */

  15. #15
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Ce n'est pas une seule ligne (et je ne comprend pas vraiment comment le code règle le souci).
    Mais oui on peut s'en sortir avec des variadic template (C++11 surtout).

    On peut aussi surcharger l'operator ,, il y a un exemple de ~2003 sur hardware.fr par JoelF ^^
    (mais bon c'est probablement overkill ici)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. tableau membre d'une classe
    Par kali38 dans le forum C++
    Réponses: 4
    Dernier message: 14/01/2015, 16h41
  2. Réponses: 11
    Dernier message: 05/09/2014, 10h22
  3. Réponses: 6
    Dernier message: 02/04/2008, 14h41
  4. créer automatiquement des membres dans une classe
    Par katebe dans le forum Windows Forms
    Réponses: 15
    Dernier message: 08/01/2008, 11h21
  5. Initialiser une référence membre d'une classe
    Par NicolasJolet dans le forum C++
    Réponses: 2
    Dernier message: 18/03/2006, 12h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo