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 :

[C++][Qt] Projet de Développement: Conseils et bonnes pratiques


Sujet :

C++

  1. #41
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Ok! Je vais chercher de ce coté là alors.

    Encore une fois, merci

  2. #42
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Les QTimer fonctionnent bien, a priori exactement ce que je recherchais.
    Après différents tests annexes, je pense pouvoir me ré-atteler au projet!

    Il y a quelques temps (voir page 2):
    Citation Envoyé par koala01 Voir le message
    Personnellement, je transmettrait une référence sur la structure au constructeur des classes qui en ont besoin...

    Cela donnerait quelque chose proche de...
    J'ai pour le moment une fenêtre toute simple, avec un bouton qui appelle le module principal qui devra gérer la succession des différents modules.
    J'ai testé cela:
    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
    #include "FenPrincipale.hpp"
     
    FenPrincipale::FenPrincipale()
    {
        this->resize(200,100);
        go = new QPushButton("Go", this);
        layout = new QVBoxLayout;
        layout->addWidget(go);
        setLayout(layout);
        connect(go, SIGNAL(clicked()), this, SLOT(clicGo()));
    }
     
    void FenPrincipale::clicGo()
    {
        QMessageBox::information(this, "Info", "Début du Programme Principal");
        Programme_Principal prgm;
        prgm.execute();
        QMessageBox::information(this, "Info", "Fin du Programme Principal");
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #ifndef GLOBALES_H
    #define GLOBALES_H
     
    #include <string>
     
    namespace Globales {
    struct Variables {
        std::string test;
        std::string essai;
     
        Variables() : test("initialisation de test"), essai("initialisation de essai"){}
    };
    } //namespace Globales
    #endif // GLOBALES_H
    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
    #ifndef PROGRAMME_PRINCIPAL_H
    #define PROGRAMME_PRINCIPAL_H
     
    #include "modele/Globales.hpp"
     
    struct Globales::Variables;
     
    class Programme_Principal
    {
    public:
        Programme_Principal(Globales::Variables & Donnees);
        void execute();
     
    private:
        Globales::Variables & donnees;
    };
     
    #endif // PROGRAMME_PRINCIPAL_H
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #include "Programme_Principal.hpp"
     
    Programme_Principal::Programme_Principal(Globales::Variables & Donnees):donnees(Donnees){}
     
    void Programme_Principal::execute()
    {
    }
    En somme, le programme n'est sensé rien faire de bien "visuel", mais c'était déjà pour démarrer.

    A l'exécution, sous Qt Creator, j'ai 2 problèmes:
    1- ...Programme_Principal.hpp:6: avertissement : declaration 'struct Globales::Variables' does not declare anything
    2- ...FenPrincipale.cpp:16: erreur : no matching function for call to 'Programme_Principal:: Programme_Principal()'

    Le premier n'est pas bloquant a priori, mais m'intrigue tout de même. J'ai bien défini la structure avant la classe et suivi les conseils de koala01, mais il doit y avoir quelque chose qui m'échappe.

    La seconde est logique, puisque je ne suis pas la définition du constructeur, mais... dans FenPrincipale, pas de structure créée ni initialisée, cela se fait dans Programme_Principal, donc comment passer une référence?...
    Faut-il créer la structure encore avant? Pour la passer dans le constructeur de Programme_Principal?

    Je trouvais intéressant de ne créer la structure qu'une fois dans Programme_Principal, car c'est de lui que tout partira. Donc, en ayant en membre de la classe la structure, il serait facile de la passer aux modules suivants.

    Dois-je alors ne pas déclarer la structure avant, ne rien mettre en argument dans le constructeur et créer la structure à l'intérieur de ce dernier pour initialiser le membre?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    A l'exécution, sous Qt Creator, j'ai 2 problèmes:
    1- ...Programme_Principal.hpp:6: avertissement : declaration 'struct Globales::Variables' does not declare anything2- ...FenPrincipale.cpp:16: erreur : no matching function for call to 'Programme_Principal:: Programme_Principal()'

    Le premier n'est pas bloquant a priori, mais m'intrigue tout de même. J'ai bien défini la structure avant la classe et suivi les conseils de koala01, mais il doit y avoir quelque chose qui m'échappe.
    C'est parce que la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct Globales::Variables;
    tente de faire une déclation anticipée de la structure Variables se trouvant dans l'espace de noms Globales, alors que... la dite structure est déjà définie dans le fichier globales.h, qui est inclu juste avant la déclaration anticipée
    [quote]
    La seconde est logique, puisque je ne suis pas la définition du constructeur, mais... dans FenPrincipale, pas de structure créée ni initialisée, cela se fait dans Programme_Principal, donc comment passer une référence?...
    Faut-il créer la structure encore avant? Pour la passer dans le constructeur de Programme_Principal?

    Je trouvais intéressant de ne créer la structure qu'une fois dans Programme_Principal, car c'est de lui que tout partira. Donc, en ayant en membre de la classe la structure, il serait facile de la passer aux modules suivants.

    Dois-je alors ne pas déclarer la structure avant, ne rien mettre en argument dans le constructeur et créer la structure à l'intérieur de ce dernier pour initialiser le membre?
    Les deux possibilités sont valables:

    Soit tu crées une variable de type Globales::Variables directement dans main, avant de créer ta variable Program_Principal, et tu transmet la variable au constructeur tel qu'il est (après avoir initialisé la dite variable )

    Soit tu supprimes la référence du constructeur, et tu transformes ta référence membre Globales::Variables & donnees; en un membre "simple ( Globales::Variables donnees;), et, bien sur, il faudra penser à faire en sorte que la variable soit correctement initiailsée avant tout usage

  4. #44
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par koala01 Voir le message
    C'est parce que la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    struct Globales::Variables;
    tente de faire une déclation anticipée de la structure Variables se trouvant dans l'espace de noms Globales, alors que... la dite structure est déjà définie dans le fichier globales.h, qui est inclu juste avant la déclaration anticipée
    D'accord, donc c'est soit l'une, soit l'autre, mais pas les deux.
    Laquelle privilégier alors?
    L'inclusion du fichier ou la déclaration struct?
    Par contre dans le .cpp il faut bien remettre l'inclusion?

    Citation Envoyé par koala01 Voir le message
    Les deux possibilités sont valables:

    Soit tu crées une variable de type Globales::Variables directement dans main, avant de créer ta variable Program_Principal, et tu transmet la variable au constructeur tel qu'il est (après avoir initialisé la dite variable )

    Soit tu supprimes la référence du constructeur, et tu transformes ta référence membre Globales::Variables & donnees; en un membre "simple ( Globales::Variables donnees, et, bien sur, il faudra penser à faire en sorte que la variable soit correctement initiailsée avant tout usage
    Je vais prendre la seconde pour ce tout premier module je pense. Comme ca "j'initialise" le tout au début.
    Par contre, pour la suite, dois-je faire comme tu m'as conseillé, à savoir passer cette structure en référence à chaque constructeur des classes qui en ont besoin? Avec cela pourrai-je modifier la structure depuis l'extérieur? (permis par la référence?) Dois-je placer la "structure membre" dans la partie publique? Ou dois-je écrire des accesseurs et mutateurs?

    Je n'ai pas oublié ce que tu avais dit par rapport aux portées des structures et des classes ainsi que sur les références ^^, mais comme là je mélange le tout... ca fait une mixture pour le moment un peu trouble

    Et pour finir:
    Comment implémenter le constructeur avec la structure?
    J'ai comme unique membre de Programme_Principal "donnees" du type de la structure.
    Quand je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Programme_Principal::Programme_Principal()
    {
        Globales::Variables donnees;
    }
    Le compilateur ne me renvoie pas d'erreur mais il souligne donnees comme variable inutilisée. Dois-je m'en soucier ou est-ce la bonne méthode?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    D'accord, donc c'est soit l'une, soit l'autre, mais pas les deux.
    Laquelle privilégier alors?

    L'inclusion du fichier ou la déclaration struct?
    Utilises la déclaration anticipée chaque fois que tu le peux (c'est à dire : chaque fois qu'il te suffit de connaitre le nom d'une classe ou d'une structure, mais que tu n'essayes pas d'accéder à son conenu dans le fichier dans lelquel se trouve la déclaration anticipée) et l'inclusion du fichier chaque fois que tu le dois (comprends : chaque fois que tu ne déclares pas une référence ou un pointeur et / ou chaque fois que tu vas tenter d'accéder au contenu d'une structure ou d'une classe)
    Par contre dans le .cpp il faut bien remettre l'inclusion?
    Si le fichier n'est pas déjà inclus (même de manière indirecte), oui, en effet
    Je vais prendre la seconde pour ce tout premier module je pense. Comme ca "j'initialise" le tout au début.
    C'est un choix
    Par contre, pour la suite, dois-je faire comme tu m'as conseillé, à savoir passer cette structure en référence à chaque constructeur des classes qui en ont besoin? Avec cela pourrai-je modifier la structure depuis l'extérieur?
    Normalement, tu ne devrais pas...

    C'est à l'intérieur de tes modules que les modifications devraient etre apportées, et tu ne devrais donc pas (afin de respecter la loi demeter) essayer d'accéder à ta structure en elle-même
    (permis par la référence?)
    Tu peux le faire, dans le sens où ce n'est pas interdit par le langage...

    Par contre, tu ne devrais pas le faire dans le sens où il n'est jamais bon d'exposer plus que nécessaire un "détail d'implémentation.

    Normalement, ce devrait etre les fonctions membres de tes différents modules qui s'occupent de manipuler les données comprises dans Globales::Variables
    Dois-je placer la "structure membre" dans la partie publique? Ou dois-je écrire des accesseurs et mutateurs?
    Le mieux encore serait de placer ta structure dans une accessibilité privée et d'éviter le recours aux mutateurs / acesseurs
    Je n'ai pas oublié ce que tu avais dit par rapport aux portées des structures et des classes ainsi que sur les références ^^, mais comme là je mélange le tout... ca fait une mixture pour le moment un peu trouble
    Ca se comprend
    Et pour finir:
    Comment implémenter le constructeur avec la structure?
    J'ai comme unique membre de Programme_Principal "donnees" du type de la structure.
    Quand je fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Programme_Principal::Programme_Principal()
    {
        Globales::Variables donnees;
    }
    Le compilateur ne me renvoie pas d'erreur mais il souligne donnees comme variable inutilisée. Dois-je m'en soucier ou est-ce la bonne méthode?
    Attention, là, tu déclares une variable de type Globales::Variables qui ne sera utilisable que dans le constructeur, et qui cache le membre de meme nom

    Et, comme tu n'en fais rien, il n'est pas vraiment étonnant que ton EDI t'indique une erreur potentielle (pourquoi créer quelque chose que tu n'utilises plas )

    Ceci dit, le mieux reste toujours d'utilier les liste d'initialisation

  6. #46
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Normalement, ce devrait etre les fonctions membres de tes différents modules qui s'occupent de manipuler les données comprises dans Globales::Variables
    Oui c'est à cela que je pensais. Et donc en passant par référence la structure quand il le faut, ces fonctions membres (ou fonctions de namespaces) pourront modifier le contenu de la structure?

    J'ai pensé aux listes d'initialisation, mais tous les exemples que j'ai vu partent de types simples. Puisque ma structure n'est pas créée antérieurement, je ne peux pas la passer dans le constructeur, ainsi, comment faire une liste d'initialisation sans avoir l'objet à mettre dans la variable?
    En faisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Programme_Principal::Programme_Principal():donnees(Globales::Variables())
    {}
    ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    [quote=Gm7468;6712410]Oui c'est à cela que je pensais. Et donc en passant par référence la structure quand il le faut, ces fonctions membres (ou fonctions de namespaces) pourront modifier le contenu de la structure?
    [QUOTE]Oui, tout à fait
    J'ai pensé aux listes d'initialisation, mais tous les exemples que j'ai vu partent de types simples. Puisque ma structure n'est pas créée antérieurement, je ne peux pas la passer dans le constructeur, ainsi, comment faire une liste d'initialisation sans avoir l'objet à mettre dans la variable?
    En faisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Programme_Principal::Programme_Principal():donnees(Globales::Variables())
    {}
    ?
    Si ta structure dispose d'un constructeur par défaut (ce qui est le cas si tu ne définis pas toi même un constructeur OU si tu définis un constructeur ne prenant aucun argument ), tu peux éviter le recours à la liste d'initialisation, les membres d'une classe (ou d'une structure) étant automatiquement construits dans l'ordre de leur déclaration (au niveau du constructeur) et automatiquement détruit dans l'ordre inverse de leur déclaration dans le destructeur

  8. #48
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Si ta structure dispose d'un constructeur par défaut (ce qui est le cas si tu ne définis pas toi même un constructeur OU si tu définis un constructeur ne prenant aucun argument ), tu peux éviter le recours à la liste d'initialisation, les membres d'une classe (ou d'une structure) étant automatiquement construits dans l'ordre de leur déclaration (au niveau du constructeur) et automatiquement détruit dans l'ordre inverse de leur déclaration dans le destructeur
    Ok, je n'avais pas essayé cette possibilité, qui me paraissait "trop simple", et elle fonctionne.
    J'ai un constructeur par défaut, qui "initialise" une partie des membres de la structure, et en ne mettant rien pour le constructeur du Programme_Principal (ni liste ni implémentation dans les {}), ca a l'air de fonctionner.

    Merci

    à bientôt pour de nouvelles questions ^^

  9. #49
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Une petite formalité, pour être sur que mon code soit "propre" (quand on en arrive à ces considérations là c'est que ca commence à être assez bien ^^).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    double const CalculDistancePointPlan(VPoint const & point, double const & a, double const & b, double const & c, double const & d)
            {
                double dist;
                dist = (a*point.getXPoint() + b*point.getYPoint() + c*point.getZPoint() + d)/sqrt(a*a+b*b+c*c);
                return dist;
            }
    Par exemple dans cette fonction toute simple de calcul de la distance d'un point à un plan. Que dois-je déclarer comme constant?
    Là j'ai tout mis... mais à mon avis... je dirais qu'une solution suffirait, non?
    - Soit déclarer la fonction comme const (double const CalculDistancePointPlan...), et pas les références vers les arguments.
    - Soit déclarer les arguments en références constantes ((VPoint const & point, double const & a, double const & b, double const & c, double const & d)) mais pas la fonction.

    Par contre, bien entendu, pour une fonction qui modifie l'un de ses arguments, seule la seconde possibilité serait acceptable.

    J'en profite pour redemander confirmation, j'ai tout passé par référence, mais seule la référence vers l'objet VPoint serait nécessaire, c'est bien ça? Car pour les types courants, cela n'apporte rien de plus que la copie?
    Quelle solution privilégier alors pour ces types? Les références ou vraiment pas?

    EDIT:
    J'ai un nouveau problème, je pense qu'il est du aux namespaces que j'utilise, mais je n'arrive pas à le résoudre...
    Voici une partie des codes:
    Fichier Initialisation.hpp
    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
     
    #ifndef INITIALISATION_H_INCLUDED
    #define INITIALISATION_H_INCLUDED
     
    ...
    #include "modele/Globales.hpp"
    ...
    #include "controleur/Transversaux.hpp"
    ...
     
    namespace Initialisation {
     
        void initialisation(Globales::Variables & datas);
        (...)
    } //namespace Initialisation
     
    #endif // INITIALISATION_H_INCLUDED
    Fichier Initialisation.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include "Initialisation.hpp"
     
    namespace Initialisation {
     
    // Module Initialisation
        void initialisation(Globales::Variables & datas)
        {
    (...)
                    General::Transversaux::AlerteMaintenance(datas, "0.4");
    (...)
        }
    } //namespace Initialisation
    Fichier Transversaux.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    (...)
    namespace General {
     
        namespace Transversaux {
            (...)
            void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
            (...)
        } //namespace Transversaux
    } //namespace General
    Si je commente l'appel à la fonction (General::Transversaux::Alerte...), tout fonctionne. Par contre, si je l'active, lors de la compilation j'ai une erreur:

    \Initialisation.cpp:48: erreur : undefined reference to `General::Transversaux::AlerteMaintenance(Globales::Variables&, QString const&, QString const&, int const&)'

    D'où cela peut-il venir?
    J'ai inclus tous les fichiers nécessaires et je nomme correctement les namespaces...

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    Une petite formalité, pour être sur que mon code soit "propre" (quand on en arrive à ces considérations là c'est que ca commence à être assez bien ^^).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    double const CalculDistancePointPlan(VPoint const & point, double const & a, double const & b, double const & c, double const & d)
            {
                double dist;
                dist = (a*point.getXPoint() + b*point.getYPoint() + c*point.getZPoint() + d)/sqrt(a*a+b*b+c*c);
                return dist;
            }
    Par exemple dans cette fonction toute simple de calcul de la distance d'un point à un plan. Que dois-je déclarer comme constant?
    Là j'ai tout mis... mais à mon avis... je dirais qu'une solution suffirait, non?
    Pour ce qui est des types primitifs (double, par exemple), si les modifications qu'ils pourraient éventuellement subire dans une fonction ne doivent pas être répercutées dans la fonction appelante, tu peux parfaitement les passer simplement par valeur.

    Il n'y a, en effet, aucun intérêt à passer des types primitifs par référence, surtout si les modifications qu'ils subissent dans une fonction ne doivent pas être répercutées dans la fonction appelante
    - Soit déclarer la fonction comme const (double const CalculDistancePointPlan...), et pas les références vers les arguments.
    Cela sous entend que, si la fonction ne modifie pas l'objet au départ duquel elle est appelée, elle reste susceptible de modifier les arguments qu'elle reçoit... Est ce ce qui t'intéresse
    - Soit déclarer les arguments en références constantes ((VPoint const & point, double const & a, double const & b, double const & c, double const & d)) mais pas la fonction.
    Ce qui sous entend que la fonction modifie l'objet au départ duquel elle est appelée (et ne peut donc pas être appelée depuis un objet constant), mais ne modifie pas les arguments qu'elle reçoit... Encore une fois, est-ce ce qui t'intéresse
    Par contre, bien entendu, pour une fonction qui modifie l'un de ses arguments, seule la seconde possibilité serait acceptable.
    ou la solution d'une fonction non constante et d'un argument (celui qui doit etre modifié ) passé par référence non constante, si la fonction modifie l'objet depuis lequel elle est appelée

    J'en profite pour redemander confirmation, j'ai tout passé par référence, mais seule la référence vers l'objet VPoint serait nécessaire, c'est bien ça? Car pour les types courants, cela n'apporte rien de plus que la copie?
    En effet
    Quelle solution privilégier alors pour ces types? Les références ou vraiment pas?
    généralement le passage par valeur plutot que par référence...

    Sauf si la fonction doit modifier la valeur de l'argument et que cette modification doit être répercutée dans la fonction appelante, toujours
    EDIT:
    J'ai un nouveau problème, je pense qu'il est du aux namespaces que j'utilise, mais je n'arrive pas à le résoudre...
    Voici une partie des codes:
    Fichier Initialisation.hpp
    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
     
    #ifndef INITIALISATION_H_INCLUDED
    #define INITIALISATION_H_INCLUDED
     
    ...
    #include "modele/Globales.hpp"
    ...
    #include "controleur/Transversaux.hpp"
    ...
     
    namespace Initialisation {
     
        void initialisation(Globales::Variables & datas);
        (...)
    } //namespace Initialisation
     
    #endif // INITIALISATION_H_INCLUDED
    Fichier Initialisation.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include "Initialisation.hpp"
     
    namespace Initialisation {
     
    // Module Initialisation
        void initialisation(Globales::Variables & datas)
        {
    (...)
                    General::Transversaux::AlerteMaintenance(datas, "0.4");
    (...)
        }
    } //namespace Initialisation
    Fichier Transversaux.hpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    (...)
    namespace General {
     
        namespace Transversaux {
            (...)
            void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
            (...)
        } //namespace Transversaux
    } //namespace General
    Si je commente l'appel à la fonction (General::Transversaux::Alerte...), tout fonctionne. Par contre, si je l'active, lors de la compilation j'ai une erreur:

    \Initialisation.cpp:48: erreur : undefined reference to `General::Transversaux::AlerteMaintenance(Globales::Variables&, QString const&, QString const&, int const&)'

    D'où cela peut-il venir?
    J'ai inclus tous les fichiers nécessaires et je nomme correctement les namespaces...
    As tu bel et bien l'implémentation de AlerteMaintenance dans un fichier *.cpp, est il correctement compilé et fait il partie de ton projet

  11. #51
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Je crois que je m'embrouille quand même un peu avec toutes ces notions...

    Citation Envoyé par koala01 Voir le message
    Pour ce qui est des types primitifs (double, par exemple), si les modifications qu'ils pourraient éventuellement subire dans une fonction ne doivent pas être répercutées dans la fonction appelante, tu peux parfaitement les passer simplement par valeur.

    Il n'y a, en effet, aucun intérêt à passer des types primitifs par référence, surtout si les modifications qu'ils subissent dans une fonction ne doivent pas être répercutées dans la fonction appelante
    Cela sous entend que, si la fonction ne modifie pas l'objet au départ duquel elle est appelée, elle reste susceptible de modifier les arguments qu'elle reçoit... Est ce ce qui t'intéresse
    Ce qui sous entend que la fonction modifie l'objet au départ duquel elle est appelée (et ne peut donc pas être appelée depuis un objet constant), mais ne modifie pas les arguments qu'elle reçoit... Encore une fois, est-ce ce qui t'intéresse
    ou la solution d'une fonction non constante et d'un argument (celui qui doit etre modifié ) passé par référence non constante, si la fonction modifie l'objet depuis lequel elle est appelée

    En effet
    généralement le passage par valeur plutot que par référence...

    Sauf si la fonction doit modifier la valeur de l'argument et que cette modification doit être répercutée dans la fonction appelante, toujours
    - Une fonction déclarée comme constante ne modifie pas l'objet duquel elle est appelée, mais cela ne suppose rien sur ses arguments?
    - Pour les types courants en argument, on utilise donc soit
    si l'argument n'a pas à être modifé;
    soit
    s'il doit être modifié.
    Mais ce que je proposais:
    n'a donc aucun sens, puisque je passais en référence (donc pour modification) un objet (de type courant) constant?

    Citation Envoyé par koala01 Voir le message
    As tu bel et bien l'implémentation de AlerteMaintenance dans un fichier *.cpp
    oui, dans Transversaux.cpp, qui inclut Transversaux.hpp, fonction dans le namespace General::Transversaux.
    Par contre, le déclaration est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
    et la définition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement, int const numPoint){...}
    (cf. les arguments par défaut, mais je crois qu'on doit bien faire comme cela)

    Citation Envoyé par koala01 Voir le message
    est il correctement compilé et fait il partie de ton projet
    je ne suis pas sur, mais je dirais a priori oui, car j'utilise d'autres fonctions d'un namespace General::XML placé dans Transversaux.hpp et .cpp et celles-ci fonctionnement.

    Le pire, c'est que Qt Creator me propose la fonction quand je tape General::Transversaux, donc il devrait la connaitre...

    EDIT: à n'y rien comprendre...
    J'ai changé la fonction de place, et je l'ai mise temporairement directement dans le namespace Initialisation:
    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
     
    #ifndef INITIALISATION_H_INCLUDED
    #define INITIALISATION_H_INCLUDED
     
    #include <QtCore>
     
    #include "modele/Globales.hpp"
    (...)
     
     
    namespace Initialisation {
     
        void initialisation(Globales::Variables & datas);
     
        void erreurInitiale(Globales::Variables & datas);
        void chargementXML(QFile & fichierXML, Globales::Variables & datas);
     
        void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
     
    } //namespace Initialisation
     
    #endif // INITIALISATION_H_INCLUDED
    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
     
    #include "Initialisation.hpp"
     
    namespace Initialisation {
     
    // Module Initialisation
        void initialisation(Globales::Variables & datas)
        {
                erreurInitiale(datas);
                chargementXML(fReturnCodes, datas);
                AlerteMaintenance(datas, "0.4");
        }
     
    // Sous-Module Erreur Initiale
        void erreurInitiale(Globales::Variables & datas)
        {
            //actions...
        }
     
    // Sous-Module Chargement XML
        void chargementXML(QFile & fichierXML, Globales::Variables & datas)
        {
            //actions...
        }
     
      void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement, int const numPoint)
      {
            //actions...
      }
     
    } //namespace Initialisation
    Les fonctions erreurInitiale() et chargementXML() fonctionnent, mais la fonction AlerteMaintenance() envoie toujours le problème:

    Initialisation.cpp:47: erreur : undefined reference to `Initialisation::AlerteMaintenance(Globales::Variables&, QString const&, QString const&, int const&)'

    Alors que cette fois on est dans le même namespace, avec des fonctions similaires qui fonctionnent!

    EDIT 2: résolu mais toujours pas compris...
    J'ai tout replacé dans Transversaux.hpp et .cpp.
    Et j'ai tout ré-écrit. Par contre cette fois, le compilateur m'a proposé quelque chose d'étrange:
    Déclaration de la fonction dans .hpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
    Comme je l'avais définie dans le .cpp précédemment: (qui posait problème)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement, int const numPoint)
    Ce que le compilateur m'a proposé: (qui, à présent, fonctionne)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void AlerteMaintenance(Globales::Variables &datas, const QString &code, const QString &supplement, const int &numPoint)
    -> Remarquer le passage de type const & argument à const type &argument
    (position du const et espace entre le & et l'argument).

    Toutes mes autres fonctions ont été faites comme la première solution, qui là n'a pas fonctionné. Pourquoi?

    EDIT 3: Compris!
    C'est tout simple: j'avais oublié un "&" pour le dernier argument, cette fois ca marche avec la première solution.

    Je suis tout de même curieux (cf. titre du post), de savoir quelle solution est à appliquer:
    - type const & argument (comme je le fais)
    ou
    - const type &argument (comme me le propose le compilateur)

    Et à ce moment il faudrait appliquer la même chose pour la déclaration (.hpp) et la définition (.cpp)?

  12. #52
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Me revoilà pour une nouvelle question, en plus des précédentes

    J'ai une classe d'objet qui fait pas mal d'actions plus ou moins complexes et élémentaires. Pour "simplifier" le fonctionnement, je me suis dit qu'il serait judicieux de séparer ces actions élémentaires de la classe. Je les ai donc placées dans un namespace dans d'autres fichiers.
    J'ai donc:
    Objet.hpp
    Objet.cpp
    Namespace.hpp
    Namespace.cpp

    Certaines fonctions du Namespace nécessitent l'objet, j'ai donc inclus Objet.hpp dans le Namespace.hpp. Jusque là aucun problème.
    Par contre, ce que j'aimerais faire, c'est utiliser ces fonctions élémentaires de Namespace dans mon objet.
    Et donc je devrais aussi inclure Namespace.hpp dans Objet.hpp.
    Cependant, lorsque je fais cela, toutes les fonctions de Namespace qui utilisent objet envoient des problèmes:
    - variable or field 'Fonction' declared void
    - 'Objet' was not declared in this scope


    Ce problème vient lorsque j'inclus Namespace.hpp dans Objet.hpp, alors que Objet.hpp est déjà inclus dans Namespace.hpp.

    Est-ce que le C++ interdit l'inter-inclusion comme cela?
    A ce moment y a-t-il une solution?
    Ou dois-je revenir à mon ancienne architecture sans le namespace?

    EDIT:
    Début de solution trouvée, mais encore une fois, je ne comprends pas bien, si on peut m'éclairer
    Dans le Namespace.hpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include Objet.hpp
     
    class Objet;
     
    namespace Namespace{
    ...
    }
    Comme cela, le compilateur ne m'envoie plus de problème.
    Mais pourquoi?
    C'est la même histoire qu'avec la structure, mais je ne comprends pas pourquoi le include ne suffit pas, et pourquoi il faut les deux... et uniquement dans le .hpp.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    Je crois que je m'embrouille quand même un peu avec toutes ces notions...

    - Une fonction déclarée comme constante ne modifie pas l'objet duquel elle est appelée, mais cela ne suppose rien sur ses arguments?
    Exactement : elle s'engage uniquement à ne pas modifier l'objet au départ duquel elle est invoquée, mais ne s'engage à rien par rapport aux objets impactés par les arguments qu'elle reçoit .

    Si les objet impactés par les arguments qu'elle reçoit ne doivent pas être modifiés, il s'agira:
    de déclarer l'objet en question comme étant constant
    de veiller à ce que les éventuels accesseurs utilisés soient constants (c'est de toutes manières une quasi obligation ) et renvoient une référence constante (ou une valeur, qui, du coup, évitera les répercussions sur l'objet d'origine)
    ==> avec comme résultat que la fonction ne pourra pas recevoir autre chose qu'une valeur (donc, sans répercussion sur l'objet d'origine) ou une référence... constante
    - Pour les types courants en argument, on utilise donc soit
    si l'argument n'a pas à être modifé;
    soit
    s'il doit être modifié.
    Mais ce que je proposais:
    n'a donc aucun sens, puisque je passais en référence (donc pour modification) un objet (de type courant) constant?
    Je présumes que tu veux dire "type primitif" (AKA char, short, int, long, long long, leur équivalent unsigned, float, double et long double)

    Mais oui, en effet, il est purement interdit d'essayer de modifier un objet passé sous forme constante (que ce soit par valeur ou référence constante): le compilateur t'insultera si tu essayes de le faire

    oui, dans Transversaux.cpp, qui inclut Transversaux.hpp, fonction dans le namespace General::Transversaux.
    Par contre, le déclaration est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
    et la définition
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement, int const numPoint){...}
    (cf. les arguments par défaut, mais je crois qu'on doit bien faire comme cela)
    Oui, numPoint est déclaré sous la forme d'un int const d'un coté et sous celle d'un int const & de l'autre...

    L'éditeur de liens cherche donc la fonction prenant une référence constante sur un entier, qu'il ne trouve pas, vu qu'elle est implémentée comme étant une fonction prenant... un entier constant


    EDIT 2: résolu mais toujours pas compris...
    J'ai tout replacé dans Transversaux.hpp et .cpp.
    Et j'ai tout ré-écrit. Par contre cette fois, le compilateur m'a proposé quelque chose d'étrange:
    Déclaration de la fonction dans .hpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement = "", int const & numPoint = 0);
    Comme je l'avais définie dans le .cpp précédemment: (qui posait problème)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void AlerteMaintenance(Globales::Variables & datas, QString const & code, QString const & supplement, int const numPoint)
    Ce que le compilateur m'a proposé: (qui, à présent, fonctionne)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void AlerteMaintenance(Globales::Variables &datas, const QString &code, const QString &supplement, const int &numPoint)
    -> Remarquer le passage de type const & argument à const type &argument
    (position du const et espace entre le & et l'argument).

    Toutes mes autres fonctions ont été faites comme la première solution, qui là n'a pas fonctionné. Pourquoi?
    EDIT 3: Compris!
    C'est tout simple: j'avais oublié un "&" pour le dernier argument, cette fois ca marche avec la première solution.

    Je suis tout de même curieux (cf. titre du post), de savoir quelle solution est à appliquer:
    - type const & argument (comme je le fais)
    ou
    - const type &argument (comme me le propose le compilateur)
    La norme précise que le mot clé const s'applique à ce qui se trouve à sa gauche, sauf s'il n'y a rien à gauche, et dans ce cas, il s'applique à ce qui se trouve à sa droite.

    Les deux versions sont donc totalement valide, à la seule différence que la pemière utilise la "règle générale" et la seconde utilise "l'exception à la règle".

    Certains (comme moi, mais je suis peut etre une exception ) préféreront utiliser la règle générale, et d'autres l'exception
    Et à ce moment il faudrait appliquer la même chose pour la déclaration (.hpp) et la définition (.cpp)?
    Du point de vue du langage en lui-même, tu peux parfaitement utiliser l'un dans la déclaration et l'autre dans la définition, voir, meme, décider d'utiliser l'un ou l'autre selon "l'air du temps" ou la direction du vent

    Cependant, il faut bien etre conscient que l'idéal est toujours de garder une certaine homogénéité, au minimum au niveau d'un projet donné

  14. #54
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Merci

    Mais donc, cela veut dire que pour déclarer quelque chose en const, la norme voudrait que le mot clé soit toujours tout à droite?

    C'est-à-dire:
    pour une fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double fonction() const;
    et pour une variable:
    Ou bien seul le type doit être déclaré constant?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double const fonction();
    Dans ce second cas, est-ce la règle de la norme ou l'exception qui est appliquée?
    Puisqu'il y a quelque chose à gauche, c'est le type, et quelque chose à droite, le nom, mais comme la gauche n'est pas vide, const ne s'applique pas au nom...
    Donc... première ou seconde solution?

    Sachant que comme tu l'as dit, l'essentiel est d'être cohérent, et pour le moment j'ai tout fait comme la seconde solution, donc c'est cohérent. Mais l'important pour moi est, d'une part de comprendre, et d'autre part que ce soit juste.

  15. #55
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    En plus de la question précédente, voici une nouvelle question.

    Elle a toujours attrait au mécanisme de signaux et slots. C'est vrai que j'ai à présent intégré le système de déclenchement action/réaction, mais je souhaiterais aller plus loin, si cela est possible.

    Suivant les conseils de koala01, j'ai le fonctionnement suivant, par exemple pour le déplacement du bras:

    Lorsque le bras a à être déplacé, on appelle la fonction deplaceBras(), celle-ci s'occupe de lancer la requête de placement par le port COM, et de démarrer le timer de contrôle.
    2 possibilités sont alors envisagées: soit on arrive à la fin du timer (il y a eu un problème lors du placement), soit le placement s'est bien effectué, on a reçu la réponse du bras disant "je suis placé".
    L'une ou l'autre des solutions aboutit donc sur une dernière fonction qui gère le résultat, par exemple 0 si tout a bien été, 1 si le timer est arrivé au bout.

    Et voici donc ma question:

    N'est-il pas possible de concentrer le tout dans une seule fonction?

    A savoir, par exemple:
    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
     
    int placementDuBras(){
        deplaceBras();
        //attente du signal?...
        return gestionResultat(reponse);
    }
     
    void deplaceBras(){
        timer.start();
        //envoie requête de placement par port COM
    }
     
    int gestionResultat(string reponse){
        if (reponse == "fin timer")
        { return 1;}
        else{ return 0;}
    }
    C'est-à-dire, n'y a-t-il pas moyen d'englober le système de signaux/slots à l'intérieur même d'une fonction, pour que, à partir de l'extérieur, on ait juste à appeler placementDuBras(), sans se soucier des signaux et slots émis/reçus et du fonctionnement interne?

    J'ai pensé à un timer "interne", qui permet de vérifier à intervalles réguliers l'état d'une variable qui sera modifiée lors de l'émission d'une des solutions (fin timer ou réception réponse). On attendrait donc effectivement tant qu'un des deux évènements n'ait pas eu lieu. Mais je trouve cette solution un peu archaïque et pas très optimisée...


    Je m'explique sur cette question:
    Toujours dans mon projet conséquent, j'ai à commander des actions par communications sur un port COM.
    J'ai donc une classe spéciale héritant de QextSerialPort, une classe spécifique développée à coté de Qt pour gérer les interfaces série. Cette classe contient différentes fonctions séparées en éléments simples:
    - Création de la requête (chaine de caractères)
    - Envoi de la requête (émission de la chaine sur le port COM)

    - Réception de données sur le port COM (chaine de caractères)
    - Traitement de la réponse (types divers)

    J'ai donc 2 possibilités (en tout cas d'après ce que j'envisage) pour faire les actions que je souhaite:
    1* soit je passe par une succession de signaux/slots
    2* soit je fais des fonctions spécifiques qui englobent ces signaux/slots

    Le problème avec la solution 1*, c'est que ca me fait une quantité gigantesque de signaux et slots à gérer ou alors de paramètres pour les gérer. Cela est du au fait que la communication COM sert à beaucoup de choses, et est utilisée depuis plusieurs endroits (modules). La réception et le traitement d'une même réponse peuvent donc, suivant les cas, appeler la suite d'une fonction ou d'une autre.

    J'ai donc imaginé (je l'espère), que la solution 2* serait plus simple à utiliser.

    Par exemple pour un simple test de la connexion COM, je devrais:

    en solution 1*:
    Envoyer la requête, et spécifier quelque part l'endroit d'où elle est envoyée. Lancer le timer. Gérer la réponse, soit fin timer, soit réponse reçue. Puis gérer l'appelant d'après ce qui a été spécifié tout à l'heure, puis émettre un signal, fonction de l'appelant, pour que tel ou tel appelant implique tel ou tel signal connecté à telle ou telle suite.

    en solution 2*:
    J'aurais une fonction pour chaque action que je souhaite réaliser. Par exemple testConnexion(), qui renverrait un entier d'après la réponse. Cette fonction en elle-même ferait toute les actions décrites en 1*, mais sans se soucier de l'appelant, puisqu'elle s'exécuterait directement dans cet appelant.

    Cela me permettrait donc d'une part de simplifier la gestion des signaux/slots en évitant la foultitude de possibilités, et d'autre part, de structurer les actions réalisées de manière propre.
    Ainsi, pour des successions d'actions, je pourrais faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    action1();
    action2();
    action3();
    directement là où j'en ait besoin;

    au lieu 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
    requete1();
     
    //signal de réception connecté à traitement
     
    traitement(id){
    if(...){emit resultat1;}
    else if(...){emit resultat2;}
    else if(...){emit resultat3;}
    }
     
    //signaux résultat 1, 2 et 3 connectés à resultat(id, appelant)
     
    resultat(id, appelant){
    if(appelant == ...){... emit retourappelant1;}
    else if(appelant == ...){ ... emit retourappelant2;}
    }
    et ce pour chaque action envisagée, avec un appelant qui hérite lui aussi de QObject pour pouvoir intégrer les signaux émis par l'objet de port COM.

  16. #56
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    N'est-il pas possible de concentrer le tout dans une seule fonction?

    A savoir, par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int placementDuBras(){
        deplaceBras();
        //attente du signal?...
        return gestionResultat(reponse);
    }
    Pour info, j'ai trouvé une classe extrêmement intéressante, à vrai dire exactement ce que je recherchais: QxtSignalWaiter. Elle permet de faire ce que j'ai matérialisé dans le code par //attente du signal?....
    On connecte l'objet à un signal, et un timer est intégré. Dans le code, on lance le timer de l'objet, et 2 possibilités de sortie sont présentes, soit la fin du timer, soit la réception du signal.
    Le post précédent est donc résolu, je vais faire mes petites fonctions qui regroupent le tout, avec le fonctionnement signaux/slots mais à l'intérieur même de la fonction, ce qui est rendu possible par cette nouvelle classe.

    Une nouvelle question me vient cependant à l'esprit:
    Le code source n'est a priori plus maintenu, mais cela pose-t-il un problème?
    La classe fonctionne, le code est en "free software", et disponible sur internet. Au-delà de cela je n'ai rien à me soucier?

    La question du post d'avant
    Citation Envoyé par Gm7468 Voir le message
    celui-ci
    est toujours sans éclaircissement

    Et cette fois uniquement une confirmation.
    J'ai quelque part dans un namespace Namespace une fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void fonctionUne(Objet & obj);
    Dans la classe Objet, j'aimerais utiliser cette fonction, j'ai donc une seconde fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void fonctionDeux(){
        ...
        Namespace::fonctionUne(*this);
        ...
    }
    Avec le this tout simple, ca ne fonctionnait pas, normal, puisque la fonction demande une référence vers un objet de type Objet et je lui envoyais un pointeur.
    Pouvez-vous me confirmer que le *this est bien ce qu'il faut? (déréférencement du pointeur pour avoir un objet, ok, mais je n'envoie quand même pas une référence...)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    Merci

    Mais donc, cela veut dire que pour déclarer quelque chose en const, la norme voudrait que le mot clé soit toujours tout à droite?

    C'est-à-dire:
    pour une fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double fonction() const;
    et pour une variable:
    Ou bien seul le type doit être déclaré constant?
    Pour les variables et les arguments, c'est le type qui doit etre déclaré constant, pour les fonctions memvre, c'est la fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double const fonction();
    Je répète ce que dit la norme
    Citation Envoyé par "la norme
    Le mot clé const s'applique à ce qui se trouve à sa gauche, sauf si rien ne se trouve à gauche, auquel cas, il s'applique à ce qui se trouve à sa droite
    A ton avis, à quoi s'appliquerait le mot clé const ici
    C'est bien ca
    Dans ce second cas, est-ce la règle de la norme ou l'exception qui est appliquée?
    cf ma question ci-dessus

    Sachant que comme tu l'as dit, l'essentiel est d'être cohérent, et pour le moment j'ai tout fait comme la seconde solution, donc c'est cohérent. Mais l'important pour moi est, d'une part de comprendre, et d'autre part que ce soit juste.
    Pour être clair :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    const type /* & / *  */ variable
    const type /* & / * */ argument
    type const /* & / *  */ variable
    type const /* & / * */ argument
    Type MaClass::fonction() const
    sont acceptés
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type const /* & / * */ fonction()
    s'applique à la valeur de retour

  18. #58
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    D'accord, c'est bien ce qui m'a semblé, donc finalement je fais... n'importe quoi.

    Quelle est la différence entre type const fonction();
    et type fonction() const; ?

    La seconde est lorsque la fonction ne modifie pas l'objet duquel elle est appelée, la première... défini le résultat comme constant?

    Mais quel est l'intérêt alors de déclarer une sortie de fonction constante, puisqu'on la met forcément dans une variable qui sera elle modifiée par la suite au besoin?

    Donc finalement pour résumer, et je me tiendrai à présent à cela:
    Pour les variables et arguments, c'est le type qui doit être déclaré constant (et pas le nom donc), exemple:
    Pour les fonctions, c'est toute la fonction, exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double fonction() const;
    Cette dernière ligne n'a de sens que pour les fonctions membres.
    Par conséquent, pour des fonctions situées dans un namespace,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double fonction() const;
    est complètement faux;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double const fonction();
    est inutile.

    C'est bien cela?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par Gm7468 Voir le message
    D'accord, c'est bien ce qui m'a semblé, donc finalement je fais... n'importe quoi.

    Quelle est la différence entre type const fonction();
    et type fonction() const; ?

    La seconde est lorsque la fonction ne modifie pas l'objet duquel elle est appelée, la première... défini le résultat comme constant?
    C'est bien cela
    Mais quel est l'intérêt alors de déclarer une sortie de fonction constante, puisqu'on la met forcément dans une variable qui sera elle modifiée par la suite au besoin?
    Si tu renvoies le résultat par valeur, presque aucun (hormis celui de "documenter" le fait que la valeur renvoyée n'est pas sensée être modifiée par la suite).

    Mais, dés que le retour de la fonction est une référence ou un pointeur sur quelque chose, l'intérêt est immense car il implique que tu ne pourras pas modifier le résultat de la fonction, et donc, cela garanti (entre autre) qu'une fonction déclarée constante ne pourra en aucun cas modifier l'objet depuis lequel elle est appelée, même de manière indirecte (par exemple : parce que l'on essayerait de modifier le résultat renvoyé par la fonction )

    Cela entre, finalement, dans le cadre du stricte respect de la const correctness
    Donc finalement pour résumer, et je me tiendrai à présent à cela:
    Pour les variables et arguments, c'est le type qui doit être déclaré constant (et pas le nom donc), exemple:
    Pour les fonctions, c'est toute la fonction, exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double fonction() const;
    Cette dernière ligne n'a de sens que pour les fonctions membres.
    Par conséquent, pour des fonctions situées dans un namespace,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double fonction() const;
    est complètement faux;
    T'as tout compris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    double const fonction();
    est inutile.
    Meme pas (cf quelques lignes plus haut), et, surement pas si c'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    UnTypeQuelconque const & fonctions();

  20. #60
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 87
    Points : 16
    Points
    16
    Par défaut
    Ok d'accord, encore une notion qui s'éclaircit petit à petit
    Merci à toi

    à bientôt

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 15/07/2014, 21h31
  2. Réponses: 3
    Dernier message: 29/06/2012, 23h03
  3. Cherche conseil Certification + bonnes pratiques
    Par babass77 dans le forum Certifications
    Réponses: 3
    Dernier message: 09/02/2009, 17h42
  4. Bonne pratique, configuration de projets
    Par gailuris dans le forum EDI et Outils pour Java
    Réponses: 7
    Dernier message: 15/12/2005, 10h57

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