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

C++ Discussion :

créer des objets dynamiquement


Sujet :

C++

  1. #1
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut créer des objets dynamiquement
    Salut

    j'ai des problèmes avec les pointeurs et mes classes;
    je ne sais pas comment créer dynamiquement des tableaux d'objets;

    l'objet est de type A avec constructeur par défaut et constructeur acceptant comme paramètre un entier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A *x=new A[16]; // pas de problème
    A *x=new A(3)[16] // gros problème!!!
    c'est quoi la solution pour créer dynamiquement un tableau d'objet en passant des paramètre aux constructeurs?? (les mêmes paramètres aux constructeurs pour tous les objets)

    aussi, est-il possible de créer dynamiquement des tableaux de n dimention???
    genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int a=4, b=76, c=9;
    int x[a][b][c]; // a, b, c ne sont pas des constantes donc erreur
    // comment utiliser le "new" pour faire ce tableau

    ps:pardonner mon français c'est ma seconde langue

  2. #2
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Salut,

    il n'est pas possible d'allouer un tableau de taille variable en l'initialisant en même temps.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int x[a][b][c]; // a, b, c ne sont pas des constantes donc erreur
    // comment utiliser le "new" pour faire ce tableaux
    --> ce code marche texto avec la norme c99.

  3. #3
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut
    dans mon bouquin (le langage C++, de Bjarne Stroustrup, sortie en 2003) c'est écrit:

    "Le nombre d'éléments et les limites du tableau doivent être une expression constants"

    donc dans l'exemple précédent, a,b et c doivent être des const int? ou je me trompe?

  4. #4
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Ca dépend de la norme que tu utilises.
    Essaie avec ton compilateur, et regarde le résultat

  5. #5
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par coyotte507 Voir le message
    il n'est pas possible d'allouer un tableau de taille variable en l'initialisant en même temps.
    Alors, comment créer dynamiquement 'n' objets en pouvant manipuler à n'importe quel moment l'objet 'i' ?

    Il y a bien la méthode des listes chaînées mais, elle ne permet pas d'accéder qu'aux objets devants ou derrière l'objet actuel.

    Puis-je créer un tableau de pointeur vers ma classe?? puis initialiser chaque pointeur individuellement (éventuellement par un new)

    ()
    Ca dépend de la norme que tu utilises.
    Essaie avec ton compilateur, et regarde le résultat
    sous turbo cpp (1991)
    sous MinGW 3.4.5

  6. #6
    Membre expérimenté
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Si, tu peux créer un tableau de taille variable, mais avec l'initialisation par défaut de l'objet.

    Ce que je voulais dire, c'est qu'en créant un tableau de taille variable, tu étais obligé d'utiliser le constructeur par défaut pour initialiser tes objets, tu ne peux pas spécifier d'arguments.

    Par conte tu peux faire:

    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
    #include <iostream>
     
    using namespace std;
     
    int main()
    {
        int a = 5, b = 18, c = 9;
        int tab[a][b][c];
        int *pointeur = &tab[0][0][0];
     
        for (int i = a*b*c; i > 0; i--, ++pointeur) *pointeur = 3;
     
        //vérification que le tableau contient bien 3 partout
        cout << tab[0][0][0] << endl;
        cout << tab[3][9][4] << endl;
        cout << tab[1][10][7] << endl;
        cout << tab[a-1][b-1][c-1] << endl;
     
        return 0;
    }
    Mais tu ne peux pas initialiser lors de la création

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Code C99 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        int a = 5, b = 18, c = 9;
        int tab[a][b][c];
    À ma connaissance, ceci ne marche pas en C++ standard, qui ne supporte pas les VLA.
    Si ça marche sous gcc, c'est que c'est supporté en tant qu'extension GNU.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Code C99 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        int a = 5, b = 18, c = 9;
        int tab[a][b][c];
    À ma connaissance, ceci ne marche pas en C++ standard, qui ne supporte pas les VLA.
    C'est bien ce que je savais mais, sous MinGW, ça marche !

    Donc, pour plus de compatibilité pour mon code, je fais comment pour créer un tableau de 'a' dimension dynamiquement (le nombre de dimension est connu à l'avance mais bien sûr pas le nombre d'élément de chaque dimension)

    J'ai essayé le new[i][j] sauf que ça me donne un message d'erreur à la compilation

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Le problème avec l'allocation dynamique, c'est qu'il faut normalement utiliser des pointeurs comme par exemple
    Si tu veux multiplier les dimensions, tu dois normalement utiliser des pointeurs de pointeurs (de pointeurs) en fonction du nombre de dimensions.

    Ainsi, pour un tableau à deux dimensions, tu dois déjà utiliser un pointeur de pointeur sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int **tab =new int* [a];
    for (int i=0;i<a;++i)
        tab[i]=new int [b];
    et pour trois dimensions, cela devient alors un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int ***tab =  new int**[a];
    for(int i=0;i<a;++i)
    {
        tab[i]=new int* [b];
        for(int j=0;j<b;++j)
        {
            tab[i][j]= new int [c];
            /* on peut envisager d'initialiser les élément ici */
            for(int k=0;k<c; ++k)
                tab[i][j][k]=7;
         }
    }
    L'avantage de ce code, c'est que tous les éléments ne sont pas forcément contigu en mémoire (tab[2][3][c-1] ne se trouve pas forcément juste avant tab[2][4][0] en mémoire )

    L'inconvénient, c'est que cela t'oblige à utiliser des pointeurs de pointeur de pointeur

    Or, la gestion de pointeurs n'est en elle-même pas évidente (au point qu'en C++ on décide déjà de ne les utiliser que quand on n'a pas le choix).

    Alors, que dire de la gestion de pointeurs de pointeurs, ou de la gestion de pointeurs de pointeurs de pointeurs (sans doute au minimum que cela devient clairement compliqué )

    L'une des solutions consiste à ce dire que, quel que soit le nombre de dimensions utilisé, on a besoin d'un nombre d'éléments équivalent au produits des tailles de toutes les dimensions, et de demander l'allocation de la mémoire pour directement ce nombre sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    /* les trois dimensions */
    int a=10;
    int b=15;
    int c=20;
    int *tab= new int[a*b*c];
    /* YAPUKA initialiser les éléments */
    for(int i=0;i<a*b*c;++i)
        tab[i]=12;
    L'accès aux différents éléments se faisant en multipliant chaque dimensions par le produit des tailles de toutes les suivante, et en additionnant les valeurs sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    /* on veut accéder à l'élément qui serait en tab[z][y][x] */
    tab[z*b*c + y*c + x ];
    Il y a cependant un risque patent: dans l'exemple donné, il faut déjà 10*15*20 = 3000 éléments contigus en mémoire...

    Imagine que, si tu donnes la valeur 1000 à a, b et c, il te faudra 1 000 000 000 éléments contigus en mémoire, et qu'il peut rapidement devenir compliqué de trouver tout cet espace contigu sur le système (surtout que le système d'exploitation n'autorise parfois qu'une quantité de mémoire limitée par application)

    Il reste une dernière alternative: utiliser la classe vector et ses possiblités.

    Cette classe fournit l'ensemble des capacités que l'on retrouve dans les tableaux C style, tout en nous évitant d'avoir à gérer l'allocation dynamique.

    Elle est, comme l'ensemble de la bibliothèque standard, disponible dans l'espace de nom std.

    Pour pouvoir utiliser cette classe, il faut inclure le fichier d'en-tête <vector>.

    Nous allons considérer notre tableau à trois dimensions comme étant un tableau contenant un tableau contenant un tableau contenant des entiers.

    Au final, nos aurons donc une variable tab déclarée sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    vector<vector<vector<int> > > tab;
    /* ou, sans la directive using namespace std; */
    std::vector<std::vector<std::vector<int> > > tab;
    (remarque les espaces séparant les différents ">", pour éviter que le compilateur ne considère qu'il s'agit de l'opérateur de flux >> )

    Le seul problème, c'est que l'on ne pourra pas créer l'intégralité des différents éléments d'un seul coup, et qu'il faudra donc ruser un peu...

    La solution va passer par des variables temporaires et peut prendre la forme, si tu veux que tous les éléments soient initialisés à la même valeur, de
    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
        int a = 10; //taille de la première dimension
        int b = 20; //taille de la deuxième dimension
        int c = 10; //taille de la troisième dimension
        int initial = 5; //la valeur initiale de tous les éléments
        /* il nous faut la première ligne (la troisième dimension)*/
        vector<int> x;
        x.insert(x.end(),c,initial);//insère c fois la valeur initiale avant la fin du tableau
        /* puis il nous faut toutes les lignes (la deuxième dimension) */
        vector<vector<int> > y;
        /* que l'on rempli avec des lignes */
        y.insert(y.end(),b,x);//insère b fois x avant la fin du tableau
        /*C'est ici que l'on déclare notre tableau[][][] */
        vector<vector<vector<int> > > tab;
        /* que l'on rempli de tableaux */
        tab.insert(tab.end(),a,y);//insère a fois y avant la fin du tableau
    Mais il serait presque dommage d'initialiser tous les éléments à une valeur donnée et de devoir passer son temps, par la suite, à modifier chacun de ces éléments séparément... Ce serait faire deux fois le travail

    L'idéal serait quand même d'initialiser directement les différents éléments avec les valeurs adéquates

    Cela pourrait se faire avec un code proche de
    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
        int a = 10; //taille de la première dimension
        int b = 20; //taille de la deuxième dimension
        int c = 10; //taille de la troisième dimension
        vector <vector < vector<int> > > tab;//déclare notre tableau à trois dimensions
        for(int i=0;i<a;++i)
        {
            vector<vector<int> > y; //déclare un tableau à deux dimensions
            for(int j=0;j<b;++j)
            {
                vector<int> x;/* déclare notre ligne*/
                /* remplissont la ligne[i][j] */
                for(int k=0;k<c;++k)
                {
                    /* la valeur peut venir de n'importe où, ici, j'ai simplement
                     * choisi de la calculer ;)
                     */
                    x.push_back(i*a*b +j*b +k);
                }
                y.push_back(x);//insérons la nouvelle ligne dans le tableau deux dimensions
            }
            tab.push_back(y);//insérons le tableaux deux dimensions dans le tableau à trois
        }
    Apres avoir initialisé le tableau, on peut très bien accéder aux différents éléments sous la forme de tab[z][y][x], et, par exemple, demander l'affichage de tous les éléments sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        for(int i=0;i<a;++i)
            for(int j=0;j<b;++j)
                for(int k=0;k<c;++k)
                    cout<<"tab["<<i<<"]["<<j<<"]["<<k<<"] = "<<tab[i][j][k]<<endl;
    Bon, comme d'habitude, je me suis laissé emporter par ma diarrhée mentale...

    Mais il me semble avoir été complet
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Mais il me semble avoir été complet
    Nope. Les codes aves les 150 new[] fuient ... dès qu'il y a une exception.
    D'où que l'on évite de faire ça à la main comme des bourrins, et des les classes toutes faites sont nos amis car ses aspects y ont été intégrés.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #11
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,
    Ainsi, pour un tableau de trois dimensions, cela devient alors un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int ***tab =  new int**[a];
    for(int i=0;i<a;++i)
    {
        tab[i]=new int* [b];
        for(int j=0;j<b;++j)
        {
            tab[i][j]= new int [c];
            /* on peut envisager d'initialiser les élément ici */
            for(int k=0;k<c; ++k)
                tab[i][j][k]=7;
         }
    }
    merci, ça répond à ma question.

    l'autre méthode (créer un tableau de a*b*c à la place de tab[a][b][c] ) n'est pas trop pratique (du point de vue d'un programmeur super inexpérimenté)

    pour la méthode du std::vector, je vais l'essayer et voir si elle m'est utile (je pense que oui mais j'aimerais voir toutes les possibilités de la classe avant de l'utiliser)

    Citation Envoyé par koala01 Voir le message
    la gestion de pointeurs n'est en elle-même pas évidente (au point qu'en C++ on décide déjà de ne les utiliser que quand on n'a pas le choix)
    tu me dis de ne pas en abuser (voir ne pas les utiliser) alors comment créer dynamiquement des objets? les références ne permettent pas de telle manip!

    avant de metre un [résolu] devant le topic, peux-tu m'éclairer et me dire ou dois-je substituer les pointeurs et par quoi (seulement quelques exemples)

  12. #12
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par lenul Voir le message
    merci, ça répond à ma question.
    C'est déjà pas mal
    l'autre méthode (créer un tableau de a*b*c à la place de tab[a][b][c] ) n'est pas trop pratique (du point de vue d'un programmeur super inexpérimenté)
    C'est pourtant de la simple mathématique
    pour la méthode du std::vector, je vais l'essayer et voir si elle m'est utile (je pense que oui mais j'aimerais voir toutes les possibilités de la classe avant de l'utiliser)
    Tu trouvera une bonne partie des informations utiles (dont l'ensemble des méthodes utilisables) à la classe vector sur http://www.sgi.com/tech/stl/Vector.html... Désolé, mais le lien est en anglais.

    Tu trouvera aussi quelques informations sur la page de la FAQ consacrée à la STL
    tu me dis de ne pas en abuser (voir ne pas les utiliser) alors comment créer dynamiquement des objets? les références ne permettent pas de telle manip!
    Ben, crée tes différents objets de manière statique (donc "sans avoir recours à l'allocation dynamique" de la mémoire), et place les dans les différents conteneurs de la STL (en choisissant celui qui convient le mieux à ton usage), et ton problème sera résolu: les éléments existeront jusqu'à ce que le conteneur soit détruit

    avant de metre un [résolu] devant le topic, peux-tu m'éclairer et me dire ou dois-je substituer les pointeurs et par quoi (seulement quelques exemples)
    Si je modifiais l'avant dernier code de mon intervention précédente en
    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
        int a = 10; //taille de la première dimension
        int b = 20; //taille de la deuxième dimension
        int c = 10; //taille de la troisième dimension
        vector <vector < vector<int> > > tab;//déclare notre tableau à trois dimensions
        for(int i=0;i<a;++i)
        {
            vector<vector<int> > y; //déclare un tableau à deux dimensions
            for(int j=0;j<b;++j)
            {
                vector<int> x;/* déclare notre ligne*/
                /* remplissont la ligne[i][j] */
                for(int k=0;k<c;++k)
                {
                    /* la valeur peut venir de n'importe où, ici, j'ai simplement
                     * choisi de la calculer ;)
                     */
                    int value=i*a*b +j*b +k;//ce n'est que quelques opérations mathématiques... aucun pointeur n'est utilisé ici
                    x.push_back(value);
                }
                y.push_back(x);//insérons la nouvelle ligne dans le tableau deux dimensions
            }
            tab.push_back(y);//insérons le tableaux deux dimensions dans le tableau à trois
        }
    cela te semblerait plus clair (pense à bien lire les commentaires )

    Comme tu peux le remarquer, il n'y a aucun appel à l'allocation dynamique dans tout le code que j'ai écrit.

    Toute la gestion (problématique et) dynamique de la mémoire est prise en charge directement par la classe vector, et, comme il s'agit d'une classe très largement utilisée, passée à la loupe par de nombreuses personnes, tu peux être quasiment sur qu'elle sera bien plus sécurisante et efficace que tout ce que tu pourrait écrire de similaire en étant un "débutant" en C++.

    Pour être tout à fait honnête, je suis très loin d'être sur que, avec mon niveau actuel (que j'ai pourtant la faiblesse de juger à "pas trop mauvais" ou à "presque bon") je puisse être en mesure de fournir quelque chose ne serait-ce qu'aussi efficace et sécurisé
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #13
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    A *x=new A(3)[16] // gros problème!!!
    Pourquoi allouer dynamiquement si le nombre à allouer est fixe ?
    Boost ftw

  14. #14
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Pourquoi allouer dynamiquement si le nombre à allouer est fixe ?
    ce n'est qu'un exemple; dans l'application que je programme, je simule un ascencseur avec une classe pour modéliser un niveau, c'est le nombre de niveau d'un immeuble qui peut varier

    Citation Envoyé par koala01
    l'autre méthode (créer un tableau de a*b*c à la place de tab[a][b][c] ) n'est pas trop pratique (du point de vue d'un programmeur super inexpérimenté)
    C'est pourtant de la simple mathématique
    oui, et j'y avais pensé avant que tu me la propose! mais son utilisation ne donne pas un code très agréable à lire
    ( [z][y][x] devient tab[z*b*c + y*c + x ] )


    Citation Envoyé par koala01
    Bon, comme d'habitude, je me suis laissé emporter par ma diarrhée mentale...

    Mais il me semble avoir été complet
    du moment que tu ne dis pas de choses incompréensible mais plutot de bonnes idées ça ne m'ennuie pas du tout

    Merci !

  15. #15
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    J'ai l'impression que tu identifie mal tes besoins ou que ton analyse n'est pas forcément complète ni correcte...

    Si je te suis bien, tu as une classe "niveau"(étage) et une autre "ascenseur".

    Il me *semble* déjà qu'un niveau et un ascenseur ne trouvent leur utilité que... dans le cadre d'un "bâtiment".

    Le nombre d'étages et d'ascenseurs ne devrait normalement pas varier une fois que le bâtiment existe.
    Un batiment est principalement défini par:
    • Les étages qui le composent
    • Les ascenseurs dont il dispose
    • son adresse
    • *éventuellement* son nom ("World Trade Center")
    • *éventuellement* son propriétaire
    • *éventuellement* d'autres informations

    Un ascenseur ne peut aller d'un étage à un autre qu'en parcourant l'ensemble des étages qui séparent l'un de l'autre (sans *forcément* s'y arrêter, mais, en tout cas, en indiquant qu'il passe à tel ou tel étage), et est défini par:
    • Son état de fonctionnement général (utilisable ou en panne)
    • L'étage auquel il se trouve
    • Le sens du déplacement qu'il effectue (il monte, il descend ou il est "à l'arrêt" (= attend qu'on l'appelle))
    • l'état de ses portes (ouvertes ou fermées)
    • un identifiant (pour savoir de quel ascenseur on parle)
    • la liste des étages auxquels il a accès (il pourrait très bien passer au RDC, puis ne pas accéder aux 40 premiers étages et ne donner acces qu'au 40 suivants )
    • Les étages auxquels on a demandé son arrêt
    • *éventuellement* une localisation ( c'est l'ascenseur deux du coin NORD-EST)
    • *éventuellement* sa restriction d'accès (réservé au service technique, au big boss, accessible à tous...)

    En ce qui concerne les étages, je verrais bien quelques "spécialisations" de l'étage:
    • Les étages "techniques" (atelier, chaufferie, buanderie, ...) à accès restreint (seules certaines personne y ont accès)
    • Les étages "communs" (hall d'entrée, restaurant, magasins, ...) d'accès plus général
    • Les étages particuliers( les étages auxquels on trouve une ou plusieurs sociétés) avec des règles d'accès variables
    • les étages privés (appartement) à accès sans doute fortement restreint

    On pourrait prévoir certaines caractéristiques particulières pour les différents types d'étages, telles que:
    • Les étages "techniques" ne peuvent être ni vendus ni mis en location
    • Les étages "communs" ne peuvent pas être vendus, mais peuvent avoir un gestionnaire (ex: un restaurant peut changer de nom ou de gestionnaire)
    • les étages particuliers et privés peuvent être vendus ou loués (mise à jour de la description de l'étage)

    Un étage est défini par
    • Sa superficie totale
    • *éventuellement* Le nombre de pièces dont il est composé
    • *éventuellement* les commodités qu'il fournit (téléphone, télédis, internet,...)
    chaque spécialisation d'étage étant définie par quelques informations supplémentaires

    Le Bâtiment servirait de médiateur (désolé, mais le lien est en anglais)entre les ascenseurs et les étages: Quand un étage change de propriétaire ou de locataire, c'est au bâtiment de s'assurer que les différents ascenseurs mettent leurs informations à jour

    Du point de vue de l'ascenseur, les seules informations dont il doit disposer en ce qui concerne les étages sont:
    • Arret demandé (booléen)
    • Acces autorisé (booléen) (selon le cas: on a introduit une clé ou on a passé une carte magnétique pour autoriser l'accès, ou, tout simplement, l'étage est d'accès illimité (ex: le rez de chaussée))
    • une description de l'étage (nom du propriétaire/de la société, "restaurant", "chaufferie"...)

    Mais il devrait disposer de ces information au minimum pour tous les étages auxquels il donne accès (et donc, pas forcément celles des étages 41 à 80 s'il ne va pas plus haut que le 40)

    Enfin, pour chapeauter le tout, je verrais bien une dernière classe dont le but serait de "créer l'immeuble" en permettant l'ajout des ascenseurs et des étages, et qui renvoie un immeuble "complet" (pour lequel il est impossible de rajouter, de retirer ou de modifier structurellement des ascenseurs ou des étages... qui ne permet "que" la vente et/ou la location des étages qui peuvent l'être).

    Comme je l'ai déjà indiqué: tout cela peut très bien se faire, en utilisant les conteneurs de la STL, sans avoir recours à l'allocation dynamique (sauf quand on crée un nouveau bâtiment, et uniquement quand on décide de rajouter un étage (et encore, c'est uniquement parce qu'il nous faut un certain polymorphisme) )
    Maintenant, je ne sais pas quels sont exactement tes besoins, et l'analyse que je viens de faire n'est peut être pas celle qui convient (entre autre, le fait de spécialiser les étages), ni forcément complète, mais tu peux sans doute te baser dessus pour affiner la tienne
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  16. #16
    En attente de confirmation mail
    Inscrit en
    Juillet 2005
    Messages
    25
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 25
    Points : 14
    Points
    14
    Par défaut
    Explication :

    Je travaille sur un projet pour l'université (je suis étudiant 3eme année en mécatronique) où je dois concevoir un ascenseur de a à z (parties mécanique - électronique - électrique - contrôle)

    à chaque niveau d'un immeuble il y a 3 capteurs pour localiser la cabine (connaître sa position exacte sur l'axe Z)
    Du coups, le nombre de capteur varie selon le nombre d'étage : 1 étage =3 capteurs, 6 étages= 6*3=18 capteurs ...

    Pour économiser les entrés (les pattes du micro-contrôlleur) les capteurs sont disposé en parallèles( tous les capteurs 0 quel que soit leurs étages sont en parallèle, et ainsi sont les capteurs 1 et aussi les capteurs 2)

    Ainsi, dans l'algorithme principal, pour représenter les capteurs, une variable sur 2 dimensions me suffit : la première représente le numéro du capteur, la seconde représente l'info que l'on souhaite avoir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int Capteur[n][2] /*
    Capteur [i][0] retourne l'état du capteur numéro i (active ou inactive)
    Capteur [i][1] retourne l'étage du capteur i actif (les autres capteurs aillant le même numéro ne le sont pas)*/
    Du coup, je n'ai pas de problème pour l'implémentassions de l'algorithme (le nombre d'élément de chaque dimension de Capteur est connu à l'avance)

    Mon problème était au niveau du GUI et de la création d'un widget pour afficher les capteurs à l'écran.
    Je travaille avec la bibliothèque Qt 4 ; chaque Capteur est affiché à l'écran dans un label (QLabel) ( la couleur du capteur à l'écran est vert/rouge s'il est actif/inactif ) c'est ce nombre de label qui varie en fonction du nombre de capteur, donc du nombre d'étage.
    Le QLabel étant une classe, je souhaite créer dynamiquement i*3 QLabel (i==nombre d'étages) en passant les arguments adéquat au constructeur du QLabel.
    Le logiciel doit-être générique (notre maquette ne fait que 3 étages mais le circuit et le logiciel doivent être fonctionnelle pour x étages sans de trop grande modification)
    Du coup, je ne peux pas fixer le nombre d'étage à l'avance mais en fonction de ce que me demandera les profs le jour de la soutenance !!!

    (si tu veux plus de détail sur le projet, envoies moi un mp pour ne pas rallonger le topic )

    Cette fois c'est moi qui m'est emporter dans l'écriture !!!

  17. #17
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Bah tu fais ce qu'on appelle un vecteur, un tableau de taille dynamique.
    Où est le problème ?
    Boost ftw

  18. #18
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En somme, pourquoi ne pas envisager l'utilisation de trois vecteurs de booléens(un pour chaque "série" de capteur), voire, pourquoi pas, un vecteur de... vecteur de booléen , le tout, créé dans ta classe Batiment.

    Cela pourrait prendre la forme, au choix, de
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    class Batiment
    {
        public:
            /* constructeur: nbEtage correspond au nombre d'étages du batiment
             */
            Batiment(int nbEtage) :capt1(nbEtage), capt2(nbEtage), capt3(nbEtage),
            etages(nbEtage)
            {
     
            }
            /* le destructeur, qui n'a rien à faire */
            ~Batiment(){}
            /* il est toujours intéressant d'être en mesure de récupérer le
             * nombre d'étages du batiment
             */
            size_t floorCount() const
            {
                return etages;
            }
            /*Méthodes permettant de positionner les capteurs
             * (test de cohérence à prévoir)
             */
            void setCapteur1(size_t pos)
            {
             for(size_t i=0;i<etages;++i)
                capt2[i]= (i==pos?  true : false);
            }
            void setCapteur2(size_t pos)
            {
             for(size_t i=0;i<etages;++i)
                capt2[i]= (i==pos?  true : false);
            }
            void setCapteur3(size_t pos)
            {
             for(size_t i=0;i<etages;++i)
                capt3[i]= (i==pos?  true : false);
            }
            /* méthodes permetttant de questionner les capteurs
             */
            size_t posisionCapteur1() const
            {
                size_t pos=0;
                while(capt1[pos])
                    ++pos;
                return pos;
            }
            size_t posisionCapteur2() const
            {
                size_t pos=0;
                while(capt2[pos])
                    ++pos;
                return pos;
            }
            size_t posisionCapteur3() const
            {
                size_t pos=0;
                while(capt3[pos])
                    ++pos;
                return pos;
            }
            /* une méthode permettant de savoir si on est à un étage donné
             */
            bool atFloor(size_t pos) const
            {
                /* je suis parti (peut etre à tort, du principe que l'on
                 * est à l'étage si les trois capteurs sont à vrai
                 */
                return capt1[pos] && capt2[pos] && capt3[pos];
            }
            /* une méthode enfin permettant de savoir à quel étage on est
             * renvoie UINT_MAX si on est entre deux étages
             */
            size_t Floor() const
            {
                for (size_t i=0;i<etages;++i)
                {
                    if(atFloor(i))
                        return i;
                    return UINT_MAX;
                }
            }
        public:
            vector<bool> capt1;
            vector<bool> capt2;
            vector<bool> capt3;
            size_t etages;
    };
    ou de
    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
    50
    51
    52
    53
    54
    55
    56
    57
    58
    class Batiment
    {
        public:
            /* constructeur: nbEtage correspond au nombre d'étages du batiment
             * nbCapteurs permet de définir un nombre de capteurs par étages
             * (des fois que vous décidiez d'en placer plus ou moins de trois)
             *
             * par défaut, on en met 3 ;)
             */
            Batiment(size_t nbEtage, size_t nbCapteurs =3) : etages(nbEtage),
            nbcapteurs(nbCapteurs)
            {
                for(size_t i=0;i<nbCapteurs;++i)
                {
                    vector<bool> tab(nbEtage);
                    capteurs.push_back(tab);
                }
            }
            /* fournis l'acces en lecture / écriture à une série verticale
             * de capteurs
             */
            vector<bool>& operator[](size_t ind)
            {
                return capteurs[ind];
            }
            /* fournit l'accès en lecture seule à une série verticale de capteurs
             */
            const vector<bool>& operator[](size_t ind) const
            {
                return capteurs[ind];
            }
            /* il est toujours intéressant de pouvoir avoir le nombre d'étages
             * du batiment
             */
            size_t floorCount() const
            {
               return etages;
            }
            /* ... ainsi que le nombre de capteurs par étage
             */
            size_t capCount() const
            {
                return nbcapteurs;
            }
            /* ...Voir, pourquoi pas, le nombre total de capteurs :D
             * (s'il faut prévoir le remplacement de tous, et vu que j'ai
             * donné la possibilité d'en mettre un nombre quelconque
             * à chaque étage)
             */
            size_t totalCapteurs() const
            {
                return etages*nbcapteurs;
            }
        public:
            vector< vector<bool> > capteurs;
            size_t etages;
            size_t nbcapteurs;
    };
    Il est juste à noter que je n'ai pas pris en compte le fait que l'ascenseur puisse passer au sous-sol...

    les possibilités d'adaptations sont nombreuses à ce point de vue particulier
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

Discussions similaires

  1. Procédure Stockée pour créer des TABLE dynamiquement
    Par GuyverZ dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 12/05/2009, 22h29
  2. Créer un objet dynamiquement
    Par soad dans le forum API standards et tierces
    Réponses: 7
    Dernier message: 08/11/2005, 14h03
  3. Travailler / Créer des objets complexes
    Par Ekinoks dans le forum OpenGL
    Réponses: 3
    Dernier message: 22/08/2005, 14h38
  4. [C#] Créer des objets Winform personnalisés
    Par KibitO dans le forum Windows Forms
    Réponses: 8
    Dernier message: 31/05/2005, 17h09
  5. Créer des objets sur la pile ?
    Par Cornell dans le forum Langage
    Réponses: 8
    Dernier message: 03/03/2003, 11h47

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