1. #1
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut déclaration en typage "auto" partagé par plusieurs fonctions

    Bonjour,

    je travaille sur une appli qui inclut une ihm sous gtkmm3.
    Je me suis inspiré d'un exemple simple (tout est contenu dans une fonction main qui affiche une simple fenêtre avec bouton exit)
    Je veux éclater en plusieurs fonctions, voire plusieurs fichier ce qui concernait le contenu de cette fonction.

    Dans cette fonction main() était déclaré refBuilder de la sorte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto refBuilder = Gtk::Builder::create();
    ce que je comprends de cela est que refBuilder est déclaré "autotypé" en fonction du retour de la fonction create(), et en même temps définit par la valeur de ce retour.
    cela est-il exact?

    Seule la fonction main() utilisais refBuilder (seule fonction du projet dans l'exemple)

    Comment élargir la portée de refBuilder à d'autres fonctions du même cpp? à d'autres fonctions d'un autre cpp?
    Pour des variables déclarées avec leur type connu, je m'en sort, car je les déclare hors des fonctions, et si il faut, en "externe" dans un .h
    mais je ne vois pas comment déclarer une variable en auto hors d'une fonction (et pour l'instant je ne trouve pas le type retourné par la fonction create).

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    Bon j'ai aussi d'autres façons d'organiser mon code, mais peut-être que j'auri moins de souplesse au fur et à mesure qu'il s'étoffera,

    et puis la question reste intéressante non?

  3. #3
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 427
    Points : 9 900
    Points
    9 900

    Par défaut

    Je ne sais pas ce que vous entendez par "autotypé".
    Concrètement, "auto" demande juste au compilateur de calculer à la compilation le type à droite de l'affectation et de faire en sorte que la variable ait le même type.
    Ce n'est pas du typage dynamique mais de l'inférence de type.
    Cela permet de plus facilement modifier le code, les signature en particulier, sans avoir à tout reprendre. Et aussi de ne pas utiliser explicitement les types avec des noms à coucher dehors que nous donne la STL, par exemple.

    Mais quand on définit et on implémente une fonction, le type de la valeur de retour et les types des paramètres sont maitrisés.
    Si la fonction marche avec n'importe quel type, ou avec plusieurs types, généralement, on passe par des fonctions Template qui ne demande pas à avoir la valeur explicite des types paramètres, l'inférence de type faisant aussi son travail.

    EDIT :
    Pour des variables déclarées avec leur type connu, je m'en sort, car je les déclare hors des fonctions, et si il faut, en "externe" dans un .h
    Ça, c'est caca, c'est des variables globales, et c'est pas bien.
    Forcez-vous à passer tout ce qu'utilise une fonction libre par ces paramètres.
    Si c'est un méthode/fonction d'instance, l'utilisation des champs d'un objet permet d'y stocker un contexte.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    par auto j'entends dont le type est automatiquement affecté après évaluation. Visiblement là dessus je ne me trompe pas, même si je n'utilise par forcément le bon langage ...

    Je réduis au maximum (mon maximum, à ma portée) l'utilisation des variables globales, mais suis limité pour trouver, systématiquement, une alternative efficace, pas encore plus "caca", et que je comprends.

    J'ai beau lire la multitudes de réflexions à ce sujet, et comprendre les problèmes de partages de variables (du moins suffisamment pour comprendre que ce n'est pas une bonne méthode que les définir globales), j'ai du mal à saisir les mécanismes pour y remédier, les explications ne sont pas tj faciles à suivre pour un non-expert, et pas tj accompagné de bons exemples pédago non plus.

    J'essaie d'apprendre, alors si vous savez m'orienter vers un document fait pas des "experts", pour les novices, et donc accessible et accompagné d'exemples, je suis très très très preneur.

    MERCI

  5. #5
    Membre expert
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    610
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : décembre 2015
    Messages : 610
    Points : 3 095
    Points
    3 095

    Par défaut

    Citation Envoyé par niconol Voir le message
    par auto j'entends dont le type est automatiquement affecté après évaluation. Visiblement là dessus je ne me trompe pas, même si je n'utilise par forcément le bon langage ...
    Justement non. Aucun type n'est choisi après évaluation en C++.
    Le C++ est un langage à typage strict tous les types sont définis au moment de la compilation. bacelar à clairement indiqué le rôle du mot auto dans ton cas; c'est celui retourné par la fonction et qui est complètement défini indépendamment de ce qui se passera quand le code s'exécutera.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    c'est très frustrant, de vouloir dire la même chose mais de ne pas se comprendre.
    J'ai bien lu et compris que c'est le compilo qui détermine le type.

    Alors je ne dis pas évaluation, je dis déduction, détermination, .... calcul comme le dis bacelar?

    Bon, en tout cas, merci pour ces précisions et cette leçon de vocabulaire.

  7. #7
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 427
    Points : 9 900
    Points
    9 900

    Par défaut

    Bon, en tout cas, merci pour ces précisions et cette leçon de vocabulaire.
    Tu peux nous prendre pour des relou avec ce "détail" mais ce n'est pas un détail.
    C'est la différence FONDAMENTALE entre un langage fortement typé comme le C++ avec les langages à typage dynamique.
    En C++, le "calcul" du type se fait sur les types, au moment de la compilation, et que sur les types, tandis que dans les langages type JavaScript, le "type" de la variable est déterminé au moment de l'évaluation au Runtime et sera fonction des valeurs passées.
    C'est une manière totalement différente de "penser" (on parle de paradigme). Les mot-clés du langage sont imprégnés par cette manière de penser.

    Le "var" du Javascript n'a rien à voir avec l'"auto" du C++.
    Si c'est clair pour toi, c'est OK.

    Les variables globales, c'est une très mauvaise solution à tout un tas de problème.
    Chaque problème dispose d'une ou de plusieurs solutions correctes.
    Il est donc impossible de dire simple "remplace les variables globales par X ou par Y", car le problème n'est pas les variables globales mais la chose qui a été "solutionné" avec ces cochonneries.
    Il faut analyser "finement" le problème qui t'as conduit à utiliser une variable globale pour avoir une bonne solution au vrai problème initial.

    Comment élargir la portée de refBuilder à d'autres fonctions du même cpp? à d'autres fonctions d'un autre cpp?
    Pourquoi ne pas passer cette variable en paramètre de ces fonctions ?

    (et pour l'instant je ne trouve pas le type retourné par la fonction create
    RTFM
    https://developer.gnome.org/gtkmm/st...4c2c16458403ce
    Comme vous pouvez le voir, c'est un nom du type est à coucher dehors.
    Après, il faut relativiser le machin. C'est un Design Pattern assez connu, "Builder", et la manière de l'utiliser est spécifique à ce Design Pattern.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto refBuilder = Gtk::Builder::create();
    le type ne m'est pas (directement) connu, c'est le compilateur qui le calculera
    donc je ne sais pas comment passer cette variable en argument d'une prochaine fonction

    Bacelar pointe vers l'API
    qui me renseigne sur la fonction create()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static Glib::RefPtr<Builder> Gtk::Builder::create ( ) static
    un peu facilement, ou naïvement, j'ai tendance à en déduire que le type retourné est Glib::RefPtr<Builder>
    bien que je trouve cela un peu louche, je remplace "auto" par "Glib::RefPtr<Builder>"
    et donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Glib::RefPtr<Builder> refBuilder = Gtk::Builder::create();
    le compilo ne reconnait pas "Builder", je remplace par Gtk::Builder
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Glib::RefPtr<Gtk::Builder> refBuilder = Gtk::Builder::create();
    compile correctement

    Et je commence donc à découper mon main() dans des fonctions séparées, en définissant des fonctions du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    fonction1(Glib::RefPtr<Gtk::Builder> a)
    {
    ....
    }
    visiblement, le paramètre passe bien, pas d'erreur à la compil, pas de pb à l'exécution

    puis je déplace cette même fonction dans un nouveau fichier, ça ne devrait pas poser de soucis au sujet du passage par argument, mais ma fonction utilise aussi une autre variable, qui est globale (p_main_dialog_basic):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void function_test(Glib::RefPtr<Gtk::Builder> a){
    a->get_widget("main_dialog_basic", p_main_dialog_basic);
    }
    dois-je aussi nécessairement la passer par argument, car je ne veux pas la garder globale?

    ce ne doit pas être difficile, mais ça devient très contraignant pour les fonctions qui vont utiliser un grand nombre de variable.

    Si les variables sont liées (par exemple plein de pointeurs vers chacun des widgets d'une même fenêtre), je peux faire une structure, passer la structure en argument, et accéder à ses membres dans la fonctions. Est-ce une solution intelligente?

    Mais si les variable ne sont pas liées, proches (probablement pas le bon mot) (par exemple des pointeurs de fenêtres, un compteur de clic souris, le niveau d'une GPIO, la valeur d'un timer ....), j'ai l'impression que ça devient idiot de réaliser une énorme structure englobant toutes ces variables ..... Quelle alternative puis-je envisager?

    Il faut analyser "finement" le problème qui t'as conduit à utiliser une variable globale pour avoir une bonne solution au vrai problème initial.
    Si j'analyse pourquoi j'utilise des variables globales ... Bien souvent c'est uniquement parce que l’accès (lecture ou écriture) est nécessaire à plus d'une fonctions.
    Vous m'avez fournit une alternative, merci encore.
    Mais dans mon appli, par exemple, je crée un tableau de CV::MAT dans une fonction, je le rempli dans deux autres, je le lis dans deux autres (et ces 4 dernières fonctions sont appelées par 5 ou 6 autres fonctions). Mon réflexe, maladroit a été de déclarer mon tableau de CV::MAT en global.
    Dans cette situation, le passage par argument (structure ou pas) ne me parait pas adapté. Me trompe-je? Quelles sont les autres pistes à envisager?

    et pour finir, non Bacelar, je ne te, ni ne vous, prends pour des relou, et je préférerai que l'on ne suppose pas des choses de cette nature entre nous.
    Je respecte énormément l'aide que tu, vous, m'apportez, le temps que vous accordez aussi aux novices en mal de connaissance et à l'enseignement.

  9. #9
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    4 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 4 722
    Points : 19 490
    Points
    19 490

    Par défaut

    Citation Envoyé par niconol Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto refBuilder = Gtk::Builder::create();
    le type ne m'est pas (directement) connu, c'est le compilateur qui le calculera
    Bien sûr que si il t'est connu. Sinon le code ne compilerait pas.
    Tu regardes la signature de Gtk::Builder::create et son type de retour en particulier.

    Citation Envoyé par niconol Voir le message
    un peu facilement, ou naïvement, j'ai tendance à en déduire que le type retourné est Glib::RefPtr<Builder>
    Non, tout à fait logiquement et c'est exactement la façon de faire.

    Citation Envoyé par niconol Voir le message
    le compilo ne reconnait pas "Builder", je remplace par Gtk::Builder
    Parce que Builder::create est déjà/englobé dans le namespace gtk.

    Citation Envoyé par niconol Voir le message
    visiblement, le paramètre passe bien, pas d'erreur à la compil, pas de pb à l'exécution
    Copier un compteur de référence est un bon moyen de tuer tes perfs.
    Copier de manière générale est un piège. Heureusement il existe les références constantes.

    Citation Envoyé par niconol Voir le message
    dois-je aussi nécessairement la passer par argument, car je ne veux pas la garder globale?
    L'argument est un des moyens de passer une information. Pas le seul.

    Citation Envoyé par niconol Voir le message
    ça devient très contraignant pour les fonctions qui vont utiliser un grand nombre de variable.
    Peut-être parce que tu penses à l'envers. Si ta fonction prend trop de paramètres, pourquoi ce serait pas une fonction membre avec des variables membres ?
    Si ces paramètres sont liés, pourquoi ne sont-ils pas dans une structure Param ?
    S'ils ne sont pas liés : que font-ils là ?! Ont-ils du sens ?!

    Citation Envoyé par niconol Voir le message
    Si les variables sont liées (par exemple plein de pointeurs vers chacun des widgets d'une même fenêtre), je peux faire une structure, passer la structure en argument, et accéder à ses membres dans la fonctions. Est-ce une solution intelligente?
    Pourquoi ce ne le serait pas ?
    Tes variables sont liées, tu les lies dans une structure. Je vois pas ce que ça peut avoir d'aberrant ?
    Coder c'est avant tout de la logique. Du GBS (gros bon sens) comme disait un prof à moi. C'est pas 2 mots mis bout à bout qui ont une réaction magique.
    Après le POD reste une utilisation restreinte, et on parlera vite d'une classe en terme de services.

    Citation Envoyé par niconol Voir le message
    Si j'analyse pourquoi j'utilise des variables globales ... Bien souvent c'est uniquement parce que l’accès (lecture ou écriture) est nécessaire à plus d'une fonctions.
    Ceci est de loin la pire des justifications.
    Dans l'absolu un programme c'est vite complexe, et tu as vite besoin de plusieurs trucs à plusieurs endroits. C'est pas pour rien qu'on parle d'architecturer un programme, de dépendances entre les modules etc.
    Quand ton électricien ajoute une lampe dans la chambre du 3° étage, il s'en fout du tuyau d'eau du sous-sol n'est-ce pas ?
    Quand je travaille sur une fenêtre particulière, je me moque des 300 autres et tous leurs boutons.
    Tout doit est rangé et avec une portée et accessibilité logique. Ca ajoute en clarté et surtout ça limite les conneries.

    Citation Envoyé par niconol Voir le message
    Mais dans mon appli, par exemple, je crée un tableau de CV::MAT dans une fonction, je le rempli dans deux autres, je le lis dans deux autres (et ces 4 dernières fonctions sont appelées par 5 ou 6 autres fonctions). Mon réflexe, maladroit a été de déclarer mon tableau de CV::MAT en global.
    Quel est l'intérêt de/ pourquoi avoir découpé ces fonctions comme ça si ça n'a aucun sens quand tu en parles ?!
    Une fonction qui crée un CV::MAT ? Avec juste return CV::Mat(); dans le corps ? Intérêt plus que nul.
    2 fonctions pour remplir une matrice ?!
    Que tu aies 2 ou 10000 fonctions qui lisent et utilisent le tableau : mettre le tableau en globale est stupide. Tu limites ton application à utiliser et travailler sur 1 seul et unique tableau à la fois. Même s'il s'agissait de son seul but, c'est ridicule et passer le tableau en const& serait de toute façon bien 1 milliard (au moins) de fois mieux.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    Salut Bousk,

    Copier un compteur de référence
    Je ne comprends pas.
    en faisant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Glib::RefPtr<Builder> refBuilder = Gtk::Builder::create();
    puis
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function_test (refBuilder);
    Je croyais passer l'argument par valeur et non par référence (si ça a quelque chose à voir)
    mais peut-être n'est ce pas judicieux de s'attarder (pour le moment) là dessus, ou bien si?

    Peut-être parce que tu penses à l'envers
    oh, oui, je pense à l'envers, et me retrouve avec un programme d'un peu plus de 1000 lignes (je sais c'est peu), que j'ai quand même réussi à éclater en pas mal de fonctions et une petite dizaine de .cpp, et à réduire à 15 (je sais, c'est beaucoup) variables globales.

    Si ta fonction prend trop de paramètres, pourquoi ce serait pas une fonction membre avec des variables membres ?
    Si je comprends bien, par exemple, créer une classe (salve_de_mat), avec ses attributs (la tableau de mat et +) et ses méthodes (read, write, compte,compare ...) ?
    Mais la classe, et ses membres et méthodes qui doivent être publiques, deviennent accessibles par toutes les fonctions du .cpp. N'est ce pas toujours trop permissif? Et si je veux un accès par une fonction d'un autre .cpp, comment faire autrement que comme je faisais (déclarée externe dans un .h)?

    A ce stade, je me dis que c'est peut-être plus difficile de modifier mon soft vers une architecture C++ que de penser tout de suite en mode C++
    et si vous pensez que je suis trop à la ramasse, n'hésitez surtout à arrêter d'essayer de m'éduquer, avant que les bras ne vous en tombe.

    Je veux penser c++.

    Merci

  11. #11
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 427
    Points : 9 900
    Points
    9 900

    Par défaut

    Je croyais passer l'argument par valeur et non par référence (si ça a quelque chose à voir)
    mais peut-être n'est ce pas judicieux de s'attarder (pour le moment) là dessus, ou bien si?
    Là, je pense que vous êtes dans la période délicate de l'apprentissage.

    Ce n'est plus des problèmes basiques syntaxiques, avec lesquels vous avez besoin de vous battre depuis le début de l'apprentissage, que vous vous battez.
    C'est bien des problèmes plus "philosophique" du développement C++.
    C'est les notions de "best-practice", qui n'ont rien à voir avec la syntaxe du langage, mais des manières de faire et d'aborder les problèmes qui fonctionnent bien et facilement avec les outils du langage lui-même ou des outils offerts par d'autres dans le contexte du langage.

    Pour les personnes habitués, et qui maitrisent plusieurs langages, ces notions en deviennent naturelles, mais ce n'est pas le genre de trucs directement abordé dans les cours sur un langage à proprement dit.

    Ici, on n'est sur un Design Pattern "Builder". Or, la sémantique d'un builder, c'est de faire un objet qui aide à construire une autre type d'objet, beaucoup plus complexe à initialiser ( connexion à une base de donné, décodage de fichiers de configuration complexe, etc...).
    Or le fait de créer un builder avec un simple "new Builder()", c'est pas vraiment le genre de la maison, car il doit prendre en compte des trucs pour simplifier la création de l'autre proprement dit.
    C'est tellement pas le genre de la maison que vous disposez d'une méthode statique "create" à la place d'un constructeur.

    Or, en passant par copie le builder en argument d'une fonction, on est clairement hors des clous habituels de l'usage d'un builder.
    En le passant par copie, vous avez très probablement fait un clonage de "surface" du builder, avec tous les problèmes potentiels que cela engendre.
    Si ce cas d'usage n'est pas explicitement donné dans la documentation, je chercherais même pas à tester.
    Il y a dans le C++ des mécanismes qui devraient interdire se cas d'utilisation (rendre une classe non copiable par exemple), mais sur de vieilles librairies, c'est le genre de détails qui n'étaient pas forcement pris en compte lors de la conception des classes.

    Donc SI IL EST TRES IMPORTANT DE S'ATTARDER SUR LE MODE DE TRANSMISSION D'UN ARGUMENT ET ENCORE PLUS QUAND C'EST UN BUILDER.

    Le passage par référence constante devrait êtes le mode de passage par défaut. Ici je pense que c'est au moins par référence qu'il faut passer le builder.

    1000 lignes et 15 variables globales, c'est un ratio énorme. Une ou deux variables globales parce qu'on utilise de vieux machins tout moisi, c'est le maximum, même sur des programmes de millions de lignes.
    En faites, plus il y a de ligne, moins il y a de variable globale car plus il y a de probabilité que ça vous pète à la gueule au pire moment.

    créer une classe (salve_de_mat), avec ses attributs (la tableau de mat et +) et ses méthodes (read, write, compte,compare ...) ?
    Vous devriez commencer par la conception de l'API d'une classe, donc les services qu'elle offre, donc que les méthodes publiques.
    Les champs et les méthodes non publiques sont des détails d'implémentation que le code client n'a pas à connaitre et qui doit pouvoir changer très facilement.

    Mais la classe, et ses membres et méthodes qui doivent être publiques,
    C'est quoi membres pour vous ? Un champ ou une méthode ? Normalement, c'est les 2 réunis.

    deviennent accessibles par toutes les fonctions du .cpp.
    Au que oui, c'est donc pour ça que la visibilité par défaut, c'est private, merci aux concepteurs du C++ (mais qui n'ont pas eu le même génie pour le passage des arguments, pour cause de compatibilité avec le C, je suppose.).

    N'est ce pas toujours trop permissif?
    C'est pour ça qu'il ne faut pas tout mettre en publique, mais juste les méthodes qui ont été conçus pour être visible de l'extérieur.

    Et si je veux un accès par une fonction d'un autre .cpp,
    C'est pas comme ça que vous devez raisonner, ce n'est pas en terme de .cpp ou de .h.
    C'est en termes de classe.
    Si vous concevez une méthode dans une classe pour qu'elle soit accessible par du code client, vous la déclarez publique dans le .h, c'est tout.
    Le code client qui a besoin d'un service cherche la classe qui l'offre et il fait le #include du .h qui va bien, basta.

    comment faire autrement que comme je faisais (déclarée externe dans un .h)?
    On ne le fait que si c'est justifier.
    Une méthode n'est à être publique que si elle a été explicitement conçus pour être appeler de l'extérieur.

    J'ai l'impression que vous vous posez des questions qui n'ont pas lieu d'être, si vous prenez la peine de concevoir à minimum vos classes.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    ça fait un grand pas pour moi l'histoire des builder, voire un grand écart, c'est douloureux....

    Je vois 2 "priorités",
    faire une classe pour mon histoire de tableau de CV::Mat (dans un premier temps), ça va avoir pas mal de répercussion, un peu dans tous les sens, je vais bien voir si je m'en sors.
    m'occuper du passage par référence de Builder

    cela devrait aussi m'aider à orienter mon esprit vers le paradigme C++, pour l'avenir. C'est bien en codant que l'on devient codeur, non?

    C'est quoi membres pour vous ?
    pardon, je voulais dire attributs, ou champs

    En tout cas je vous remercie infiniment à nouveau pour votre attention, et vos enseignements (patients, pertinents, et agréables).

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    Bonjour,
    je suis passé à l'action,
    J'ai créé un belle classe (à mon goût), avec un certain nombre de méthodes publiques et d'attributs privés et publics.
    J'en ai perdu 5 variables globales, et le code est globalement allégé, et mieux compréhensible pour qq de l'extérieur je crois. Je viens de prendre goût, enfin, aux classes.

    Néanmoins, dans cette solution, reste un point noir pour moi, toujours le même, j'ai déclaré cette classe externe, car j'ai besoin d'accéder à ses méthodes depuis d'autres fonctions extérieures (je ne vais tout de même rentré tout mon code dans une classe ...), ce qui ouvre grand les portes vers tous ses membres publics.

    Dois-je continuer de me tracasser à ce sujet? Selon votre dernière réponse, Bacelar, j'ai l'impression que non.

    En tout cas je suis motivé pour continuer à orienter mon code existant vers le C++, et y penser plut tôt dans la conception de tout ce qui reste à venir.

  14. #14
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 427
    Points : 9 900
    Points
    9 900

    Par défaut

    J'ai créé un belle classe (à mon goût), avec un certain nombre de méthodes publiques et d'attributs privés et publics.
    Attention, ne mettez en public que ce qui a été conçu pour être accessible de l'extérieur, par du code "client".
    C'est rarement le cas de toutes les méthodes, et rendre des champs/attributs publics c'est très exceptionnel.
    Le but de ce qui est public dans une classe, c'est que cela ne change rien à l'usage de celles-ci, si l'on change radicalement les implémentations à l'intérieur de la classe.

    et le code est globalement allégé, et mieux compréhensible pour qq de l'extérieur je crois.
    Alors, c'est que vous avez bien travaillé.

    j'ai déclaré cette classe externe,
    C'est à dire ???

    car j'ai besoin d'accéder à ses méthodes depuis d'autres fonctions extérieures
    Normal, mais attention à ne pas faire une API de classe non cohérente. Toutes les fonctions/méthodes d'une classe doivent avoir un même niveau d'abstraction.
    Montrez nous le .h d'une de vos classes, SVP.

    (je ne vais tout de même rentré tout mon code dans une classe ...),
    Surtout pas, cela perdrait tout l'intérêt de la POO.

    ce qui ouvre grand les portes vers tous ses membres publics.
    Attention à une conception "au file de l'eau", du genre "j'ai besoin de ça, je vais l'implémenter dans cette classe".
    En faisant ainsi, vous créerez des classes fourre-tout sans cohérence et donc très compliquer à maintenir.
    Quand vous êtes devant la question "Comment je fais ça ?", vous devez vous dire "Quelle classe est sensée gérer ce truc ?".
    - Soit vous avez rien et vous concevez une classe qui répond au besoin, mais vous devez concevoir la classe indépendamment de votre besoin actuel mais comme un tout cohérent, le besoin initial sera comblé "par effet de bord".
    - Soit vous avez déjà une classe mais qui ne convient pas parfaitement à votre besoin, reprenez la conception initiale pour voir quels détails ont été oubliés lors de sa conception et ajoutez-y des méthodes cohérentes avec le reste de l'API de la classe, voir refaite le conception totale de l'API de la classe, si vous avez complètement foiré la conception initiale (attention, ici, cela impactera le code client, donc essayez de prévoir dés la première conception tout les cas d'usage "pertinent" de la classe).

    Ca serait peut-être plus simple avec un cas concret :
    Montrez nous le .h d'une de vos classes, SVP. (BIS)

  15. #15
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    que dois je comprendre par
    code "client"
    ?


    j'ai déclaré cette classe externe,
    C'est à dire ???
    dans acq_img.h, je déclare ma classe.
    Dans acq_img.cpp j'instancie ma classe et je déclare mon objet aquisition_en_cours de classe acq_img
    dans acq_img.h, je déclare (en l'écrivant, je sens que ça va pas être bon ...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    extern acq_img acquisition_en_cours;


    et voici ma classe acq_img.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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    #ifndef ACQ_IMG_H
    #define ACQ_IMG_H
    #include "define.h"
    #include <opencv2/opencv.hpp>
    /************************************************************************/
    /* déclaration d'une classe acq_img pour la totalité d'une mesure  */
    /************************************************************************/
    class acq_img {
      public:
        cv::Mat photo_ref_cropped;
        int p_photo_write;
     
        acq_img(){};
        ~acq_img(){};
        bool take_photo_draft ();
        bool take_photo_ref();
        bool take_photo_salve();
        bool save_photo_ref();
    /*    bool save_photo_salve();
        bool process_photo_salve();
        cv::Mat cropp_img(int);*/
     
      private:
        cv::Mat photo_ref;
        cv::Mat photo_salve[NbPhotoSalve];
        cv::Mat photo_draft;
        int p_photo_read;
    };
    extern acq_img acquisition_en_cours;
    #endif
    si je crée les 3 fonctions pour l'instant en commentaire, il est vrai que mes 2 arguments public pourraient passer en privé.
    Mais en terme de niveau d'abstraction, j'ai peut-être intérêt d'envisager une nouvelle classe pour ces fonctions
    Je dois pour cela évaluer la pertinence d'une nouvelle classe... à moi de voir

  16. #16
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    4 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 4 722
    Points : 19 490
    Points
    19 490

    Par défaut

    Si tu crées une classe pour avoir une unique instance globale, tu as peut-être moins de variables globales mais ça n'est en rien mieux.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  17. #17
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 427
    Points : 9 900
    Points
    9 900

    Par défaut

    que dois je comprendre par
    code "client"
    ?
    Le code qui utilise la classe.
    La classe doit être une boite noire pour le code l'utilisant.
    Cela permet de modifier le code de la classe sans avoir à toucher au code l'utilisant : le code client.

    dans acq_img.h, je déclare (en l'écrivant, je sens que ça va pas être bon ...)
    Tu m'étonnes, en plus d'être une variable globale, c'est même plus au niveau du cpp qu'elle est globale, c'est carrément globale à tout ce qui sera "linké" en même temps.
    C'est donc encore pire qu'une variable globale "standard".

    Si vous avez besoin d'un singleton, utilisez une implémentation du Design Pattern "Singleton".
    Et encore, je ne vois pas pourquoi vous en auriez besoin.

    Vous avez mis le constructeur en public, c'est que vous pensez que le code client doit être à-même de créer un "acq_img".
    Faut être cohérent, soit il a le droit, donc pas besoin de cette globale à la noix, soit il n'a pas le droit et vous mettez se constructeur en private et vous mettez en place un Design Pattern de création d'objet, Singleton ou un autre.

    "acq_img", c'est, pour moi, pas clair comme nom.
    Et le nom c'est très important.
    Le rôle de cette classe etc, pour moi, pas clair non plus.
    "cv::Mat photo_ref_cropped", vous mettez un champ en public, très bof, mais en plus, il est d'un type très particulier, "cv::Mat", ça veut dire que le code client doit utiliser la bibliothèque "cv" et que si vous voulez utilisez autre chose pour implémenter votre classe, vous serez dans le caca.
    "int p_photo_write;", ouais, un champ en public toujours très bof, et en plus on sait pas explicitement son rôle => réserve à bug, donc pourquoi ?

    Nom de méthode redondante et vraiment pas explicite.

    Pouvez-vous exprimer clairement le rôle de votre classe ?
    Car son rôle ne transparait pas avec sa définition dans le .h (et c'est un truc qui sent pas bon).

    si je crée les 3 fonctions pour l'instant en commentaire, il est vrai que mes 2 arguments public pourraient passer en privé.
    Si "argument" veut dire champ, oui, n'hésitez même pas.

    Mais en terme de niveau d'abstraction, j'ai peut-être intérêt d'envisager une nouvelle classe pour ces fonctions
    Pour cela il faut une définition PRÉCISE du rôle de la classe.

    Je dois pour cela évaluer la pertinence d'une nouvelle classe... à moi de voir
    On en revient toujours au même, à la définition précise du rôle de votre classe.

    Si vous n'êtes pas capable de nous la fournir, personne extérieure au projet, c'est qu'elle est mal définit.

  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2012
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2012
    Messages : 81
    Points : 41
    Points
    41

    Par défaut

    Le code qui utilise la classe.
    reçu 5/5

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Si vous avez besoin d'un singleton,
    effectivement je n'utilise qu'une seule instance cette classe, donc un singleton serazit pile poil adapté (jamais utilisé, je m'y penche)

    donc effectivement, Design pattern de création d'objet .... à venir, je m'y penche, promis

    le champs public cv::Mat, je l'ai passé en privé, en créant les fonctions qui étaient commentées
    "int p_photo_write" va avoir droit au même sort sous peu

    je vais tout renommer aussi, plus intelligement pour ouvrir à la compréhension rapide

    Ma classe à pour but la gestion complète des images de la mesure, (car il s'agit d'un dispositif de mesures):
    • acquisition depuis caméra USB,
    • redimensionnement des matrices,
    • stockage sur clé usb en jpg,
    • traitement des images,
    • enregsitrement des résultats de traitement sur fichier sur clé usb


    Stockage sur clé USB des images et des résultats de traitement pouraait être implémenter dans l'objet clef dela classe device..... que j'avais récupéré ..... (montage, démontage)

    C'est trop le bazard?


    c'est la trop le b

  19. #19
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    4 722
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 4 722
    Points : 19 490
    Points
    19 490

    Par défaut

    Non tu n'as pas besoin d'un singleton. Tu as besoin de comprendre ce que tu fais.
    Un programme a une fonction main qui exécute le programme. Si tu as besoin d'un seul objet, tu ne crées qu'une seule instance de ton objet dans le main et la manipules correctement.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  20. #20
    Expert éminent
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : février 2005
    Messages : 4 427
    Points : 9 900
    Points
    9 900

    Par défaut

    Ma classe à pour but la gestion complète des images de la mesure,
    Gestion = fourre-tout
    C'est pas encore ça.
    Votre classe fait bien trop de chose.
    Elle doit faire une seule chose, mais bien.

    Essayez de découper votre problème en plusieurs, plus petit.

    acquisition depuis caméra USB,
    Créer une image depuis une caméra dans une classe "Camera", avec une méthode capture, qui renvoie une image.
    (En plus de méthode pour configurer la caméra, etc...)

    redimensionnement des matrices,
    Quelles matrices ???
    Sont-elles spécifiques à l'image ?

    stockage sur clé usb en jpg,
    Les classes qui seront en charge de la conversion en jpg ne gèrent-elles pas déjà la sauvegarde ?

    traitement des images,
    Pourquoi ne pas faire une classe en charge d'un type de traitement ?

    enregsitrement des résultats de traitement sur fichier sur clé usb
    Pourquoi ne pas utiliser les choses déjà proposé par la librairie STL du C++ ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Concaténation dans une variable partagée par 2 fonctions
    Par Aiglon13 dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 23/05/2012, 10h36
  2. Réponses: 4
    Dernier message: 26/03/2012, 22h35
  3. Réponses: 1
    Dernier message: 02/01/2006, 20h05

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