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 :

[POO] conception des classes


Sujet :

C++

  1. #101
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    ARGG, j'ai encore un problème!

    Le constructeur de Choc instancie d'abord un objet Camera, puis CFP.
    LE problème, c'est qu'il y a une instance de PDC à créer dans CFP, mais le constructeur de PDC a besoin de coeff_mul, qui n'a pas encore été calculé...
    Ce qui veut dire que je ne peux pas mettre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CFP::CFP(int num_choc, std::string nom_cfp)
    : numero_choc(num_choc), nom_composant(nom_cfp), CFP(coeff_mul)
    {
        //code
    }
    Mais seulement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CFP::CFP(int num_choc, std::string nom_cfp)
    : numero_choc(num_choc), nom_composant(nom_cfp)
    {
    	zone = 0;
    	//suite
    	PDC(coeff_mul);
     
    }
    Est ce que je peux instancier comme je viens de le faire juste au dessus??????

    Merci!

  2. #102
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    de toute manière, CFP est un pointeur, donc c'est un new que tu vas faire, donc tu peux toujours intialiser ton pointeur à NULL et ensuite lui donner un autre pointeur.

  3. #103
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    euh... oui mais PDC fait parti des attributs de CFP, non?

    Le problème est pour PDC! Comment l'initialiser, sachant que je ne connais pas coeff_mul?
    Je ne peux pas le créer autrement!

  4. #104
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    A ce moment-là, ne le construis que plus tard.

  5. #105
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CFP::CFP(int num_choc, std::string nom_cfp)
    : numero_choc(num_choc), nom_composant(nom_cfp)
    {
    	zone = 0;
    	// code pour initialiser coeff_mul
    	PDC(coeff_mul);
    		
    }
    Est-ce que ça marche pour le "plus tard"?

  6. #106
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    J'en sais rien, ça dépend du reste de ton code.

  7. #107
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Ah bon...


    Voilà mon code presque complet de cfp.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
    31
    32
    33
    34
    35
    36
    class CFP {
     
    	friend ajusterTailleVisibleEtIR();
     
    public:
    	CFP(int num_choc, std::string nom_cfp);
    	~CFP();
     
    	CImg <unsigned short> getImageIR();
        virtual setImageIR(CImg <unsigned short>);
     
    	CImg <unsigned short> getImageVisible();
    	setImageVisible();
     
    	CImg <unsigned short> warping();
     
    	std::string getNomComposant();
    	setNomComposant(std::string);
     
    	virtual setZone(int);
    	int getZone();
     
    	affichageMix(float, bool, float, bool);
     
     
    private:
    	PDC pdc;
    	CImg <unsigned short> image_IR;
    	CImg <unsigned short> image_visible;
    	CImg <>champ_deformation;
    	std::string nom_composant;
    	int zone;
    	int numero_choc;
    	float coeff_mul;
     
    }
    Et voilà le code de cfp.cpp:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    CFP::CFP(int num_choc, std::string nom_cfp)
    : numero_choc(num_choc), nom_composant(nom_cfp)
    {
    	zone = 0;
    	setImageVisible();
    	setImageIR();
    	ajusterTailleVisibleEtIR();
     
    	// Création des Points de Controle
    	PDC(coeff_mul);
     
    }
     
    CFP::ajusterTailleVisibleEtIR()
    {
        coeff_mul = 0.5f*( static_cast<float>(LARGEUR_ECRAN) /static_cast<float>(IR.dimx()) );
        IR.resize(static_cast<int>(-100*coeff_mul), static_cast<int>(-100*coeff_mul), 1, 3, 1);
        visible.resize(IR.dimx(), IR.dimy(), 1, 3, 1);
    }
     
    CFP::setNomComposant(std::string nom_cfp){nom_composant = nom_cfp;}
     
    CFP::getNomComposant {return nom_composant;}
     
    CFP::setImageVisible()
    {
    	CImg <unsigned short> visible (nom_composant);
    	image_visible = visible;
    }
     
     
    CFP::setImageIR(int num_choc)
    {
    	int num_cam = camera.getNumeroCamera();
    	int *nbimages = new int[1];
    	int cr = IRnb_images(numchoc, numcam, &nbimages);
    	importImage(num_choc, num_cam, static_cast<long> floor(nbimages*0.5 ), static_cast<long> floor(nbimages*0.5 ), ;
     
    	delete[] nbimages;
    }

  8. #108
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Euh... C'est supposé faire quoi pour toi, PDC(coeff_mul); à cet endroit du code ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

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

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par poukill
    Je me pose plusieurs questions:
    1) Dans quels cas faire hériter une classe d'une autre?
    2) Une classe avec une seule variable est-elle abbérante?
    3) Une classe peut-elle contenir des données qui ne pas vraiment propre à elle? (exemple : dans mon cas, une classe Composant qui contiendrait une variable numero_experience...)

    Bref, je vous remercie d'avance d'éclaircir ma lanterne.
    1) Il y en a plusieurs. Le plus répandu, qu'il est important d'assimiler avec les langages statiquement typés comme le C++ (Java, ...), c'est l'héritage en vu de la substituabilité. Là où on attend un objet d'un type Parent, on peut accepter (sans rupture de contrats et d'invariants) un objet d'un type fils. C'est le LSP (principe de substitution de Liskov), c'est fortement lié au polymorphisme d'inclusion (obtenu en C++ avec les fonctions membres virtuelles), c'est très étroitement lié à l'héritage public en C++.
    C'est à dire, hériter publiquement implique que la syntaxe du langage permet de tenter de substituer un objet d'un type fils là où l'on attend un type parent. Si ces types n'ont pas été écrits pour être substituables, alors le risque de mauvaises surprises est assez élevé en cas d'héritage public. Exemples types de non substituabilité: en informatique, un carré n'est-pas-un rectangle, une liste triée n'est-pas-une liste.
    On entend aussi parfois parler d'héritage "est-un", celui qui permet d'"être utilisé en place de"

    L'héritage peut aussi être utilisé pour "réutiliser du code". Une classe peut être "implémentée en termes" d'une autre classe. C'est une alternative à la délégation (un traitement est délégué à une autre classe) ; alternative plus fortement couplée. Le C++ permet facilement de mettre en oeuvre ce type d'héritage sans permettre, syntaxiquement parlant, la substitution. Cela se fait avec l'héritage privé. Je crois qu'Eiffel a aussi sa propre façon de faire pour mettre en oeuvre un héritage de réutilisation. Java et quelques autres en sont incapables, i.e. seule la composition peut être utilisée pour définir proprement une liste triée à partir d'une liste dans ces langages.
    C'est un héritage qui a beaucoup été vendu (à tord AMHA) dans les années 80/90.

    Il y a d'autres approches de l'héritage que j'utilise assez peu: pour rajouter du code à une classe existante, ... J'avais croisé un résumé plutôt pas mal sur wikipédia (en français ou en anglais, je ne sais plus).

    2) J'écris régulièrement des classes sans données. Parce que le pattern stratégie ne requiert pas nécessairement la présence d'une donnée -- je spécialise des comportements en fonction de la stratégie courante (qui se substitue à une classe qui décrit de manière assez "abstraite" le traitement à réaliser). Parce que parfois en méta-prog j'ai besoin de classes particulières polices, traits ou autres qui ne définissent que des types ou des fonctions.
    ...
    La donnée encapsulée n'est pas ce qui caractérise une classe chez moi. Je réfléchis beaucoup plus en termes d'abstraction. La donnée encapsulée n'étant alors généralement qu'un détail d'implémentation.

    3) On essaie d'avoir un couplage intelligent entre les classes. Même si on peut pafois avoir des classes de données, il est tout à fait courant d'avoir des classes qui définissent en fait des rôles. Personnellement, j'ai tendance à priviliéger cette dernière approche -- je manipule en fait assez eu des classes de données. Du coup, les données contenues ne sont qu'un détail d'implémentation (bis). Je m'interresse avant tout aux rôles et services que fournit la classe.


    Une autre question que je me pose: dois-je déclarer CFP comme classe virtuelle??? Quelles sont les conséquences (je viens du C et du java!!!!)?
    Faudra t-il recoder toutes les méthodes dans les classes filles comme en java?
    Il n'y a pas de "classes virtuelles" en C++. On a des ABC (Abstract Base Classes) qui sont des classes abstraites. Toutes leurs fonctions peuvent être virtuelles pures (sans implémentation), ce qui ressemble beaucoup aux interfaces de Java, mais aussi à celles que l'on trouve chez COM. Seules certaines fonctions peuvent être virtuelles pures. Cela est un moyen de programmer nativement (avec de l'huile de coude) par contrats -- Java ne le permet pas sans passer par des outils externes de préprocessing.
    Il est impossible d'instancier un objet d'une classe à laquelle il reste des fonctions membres virtuelles pures.

    NB: il existe aussi la notion de "classe de base virtuelle" qui est :
    - relative aux classes qui héritent (A peut être une classe de base virtuelle pour B, mais juste une classe de base pour C)
    - lié à l'héritage multiple et au partage de membres.

    i.e. "virtuel" est utilisé dans deux contextes différents.

    Oui, je me souviens de mes cours de POO en java. L'idée était toujours d'appeler une méthode de la classe mère...
    Beurk. Je n'aime pas cette approche car il est très facile d'oublier d'appeller ce qui doit l'être. Quand cela est possible (pas toujours pratique de la mettre en oeuvre simplement), je préfère le design pattern template method->
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct Base {
        void f() {
            trucs_f_toujours_faits_pre();
            do_spe_f();
            trucs_f_toujours_faits_post();
        }
    private:
        virtual do_spe_f() { /*rien par defaut; ou virtuel pur*/}
    };
     
    struct Specialization : public Base {
    private:
        virtual do_spe_f() { /*trucs propres à la spécialisation*/}
    };
    2) Les classes filles peuvent-elle avoir des variables qui ne sont pas dans la classe mère? Si oui, est-ce souhaitable? (en fait je ne pense pas que ce soit pas possible, mais n'étant pas sur...)
    J'espère bien que c'est le cas. Les classes filles qui définissent des données, voient ces données se rajouter à celles de la classe mère. Si les données portent le même nom, alors on perd l'accès (simple) aux données (au plus protégées) de la classe mère. Il y a un processus de masquage, valable sur tous les membres (données comme fonctions), à quelques nuances près.

    ...virtuel pur
    Quand on ne peut pas fournir de comportement par défaut qui ait un sens pour une fonction membre, alors "virtuelle pure" est le meilleur choix.
    C'est aussi la seule façon de définir une ABC: une ABC est une classe qui dispose d'au moins une fonction membre virtuelle pure.

    <pinaillage>"méthode" ne fait pas partie de la terminologie C++. Certains comprennent ça comme "fonction membre". D'autres considèrent que ce sont des "fonctions membre virtuelles", ce qui me parait assez consistant avec la définition UML : une méthode étant une spécialisation (ou implémentation ?) d'une opération.
    </>

    Pour implémenter une fonction du genre "is_readable (std::string &file)", comme celà est fait dans la FAQ, faut-il créer une classe fichier (pour rester dans l'esprit de la POO), ou bien alors le laisser comme une fonction, et donc créer un fichier outils.cpp où tous ces petits test seront implémentés (moins propre ???)
    C'est le genre de cas où la fonction membre serait statique (car elle ne porte sur aucun objet en particulier) (-> fonction membre de classe). Ici, il me semble que c'est avant tout un artifice pour déclarer la fonction dans une portée, pas pour dire que les fonctions membres des objets (!= classe) peuvent être implémentées à l'aide de fonctions, dans la même thématique, mais qui ne portent sur aucun objet en particulier.
    Bref, j'utiliserai un espace de noms. En plus, c'est extensible.

    Oui, mais les variables ne sont pas dans la classe ? Je ne peux donc pas faire un simple get ? (cf pièce jointe)
    Ma question est donc : comment accéder aux classes par composition? L'amitié est - elle dans mon cas un bon moyen (cf schéma ?)
    Cela sent le code orienté données. As-tu réellement besoin des données contenues dans l'objet référencé, ou alors veux-tu réaliser un traitement sur ces données contenues dans l'objet référencé.
    Même la sérialisation des données est un traitement qui peut être délégué à l'objet qui connait le mieux les données qui définissent son état.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  10. #110
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par Médinoc
    Euh... C'est supposé faire quoi pour toi, PDC(coeff_mul); à cet endroit du code ?
    Hum... C'était sensé être un constructeur pour la classe PDC! C'est pas vraiment la bonne syntaxe

  11. #111
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Et c'est aussi interdit puisque le constructeur ne peut être appelé qu'à l'initialisation, celle-ci se passe dans la liste des initialisations. Mais si tu as un pointeur vers la bête, tu dois faire un new - encore une fois, c'est du C++ -

  12. #112
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Grrrr, je vais pas y arriver...
    Suite à la magnifique remarque de Luc, je viens de passer la matinée à me documenter (design pattern). J'ai bien analysé la notion de couplage faible (l'idéal). Tout ceci remet un peu en cause mon travail de conception .
    En effet :
    1) La recopie de variable privée dans plusieurs classes à partir de la classe principale Choc(pas toujours mère...)
    2) Le problème soulevé plus haut par Médinoc et Miles sur l'instanciation de PDC (non Miles je n'ai pas de pointeurs)
    3) Certains attributs sont placés dans des classes alors qu'ils n'en font parti que pour l'implémentation (mais pas pour le rôle, cf Luc) Donc en gros, s'il est là, c'est pour m'arranger dans le code, alors qu'il faudrait penser objet pur, c'est à dire oublier le côté implémentation. Dur, dur... Ca me rappelle mes cours de java!
    4) En outre, certaines fonctions sont mises dans une classe par défaut (comme l'affichage d'une image dans une classe de composant, car en fait, un composant est toujours vu dans mon cas par une image via une caméra CCD)

    Tout ceci montre un couplage assez fort entre mes classes, ce qui entraine évidemment un problème d'ordre de création, car Caméra a besoin de CFP pour être construite intégralement (i.e remplir tous ses champs privés) et vice versa...

    Voici quand même le code pour la création de PDC. J'aurai espérer l'existence d'une astuce pour créer PDC "plus tard", et pas directement dans le "prototype"... Ca a l'air possible mais uniquement avec un pointeur, pas par composition directe d'après ce que j'ai compris Miles.
    Hé oui, il me faut ce fameux coeff_mul pour créer PDC, ce qu'on ne connait pas encore lorsqu'on crée CFP...

    Je ne sais pas si un jour je vais voir le bout de ce projet !

    MErci à vous tous.


    cfp.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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #ifndef CFP_H
    #define CFP_H
     
    #include "CImg.h"
    #include <iostream>
    #include <string>
     
    class CFP {
     
    	friend ajusterTailleVisibleEtIR();
     
    public:
    	CFP(int num_choc, std::string nom_cfp);
    	~CFP();
     
    	CImg <unsigned short> getImageIR();
        virtual setImageIR(CImg <unsigned short>);
     
    	CImg <unsigned short> getImageVisible();
    	setImageVisible();
     
    	CImg <unsigned short> warping();
     
    	std::string getNomComposant();
    	setNomComposant(std::string);
     
    	virtual setZone(int);
    	int getZone();
     
    	affichageMix(float, bool, float, bool);
     
     
    private:
    	PDC pdc;
    	CImg <unsigned short> image_IR;
    	CImg <unsigned short> image_visible;
    	CImg <>champ_deformation;
    	std::string nom_composant;
    	int zone;
    	int numero_choc;
    	float coeff_mul;
     
    }
     
    #endif
    pdc.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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #ifndef PDC_H
    #define PDC_H
     
    #include <vector>
    #include <fstream>
    #include <string>
     
    #include "CImg.h"
     
     
    typedef std::vector< std::pair <int, int> > tableau;
     
     
     
     
    class PDC {
    public:
    	PDC(float);
    	~PDC();
    	void sauveTableau();
    	void chargeTableau();
     
    	void setNomFichier();
    	std::string getNomFichier();
     
    	void setCoeffMul(float coeff_muliplicateur);
     
    	void ajouterPDCDepart(int a, int b);
    	void enleverPDCDepart(int a, int b);
     
    	void ajouterPDCArrivee(int a, int b);
    	void enleverPDCArrivee(int a, int b);
     
    private:
    	tableau tableau_depart;
    	tableau tableau_arrivee;
    	std::string nom_fichier;
    	float coeff_mul;
    }
     
    #endif

  13. #113
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Tu ne peux pas laisser pdc (la variable membre, oui) se construire avec le constructeur par défaut de sa classe puis appeler la fonction membre setCoeffMul()?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

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

  14. #114
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Si si! C'est une solution...
    Certes! Mais comme je programme comme un pied( ), mes classes sont couplées. Or dans le constructeur 'global', c'est à dire celui dont plusieurs autres classes dépendent, va justement remplir ces autres champs privés de ces classes en question...
    C'est sans doute encore trop bidouille...
    Pour voir mon diagramme -> Page 5 de ce topic. C'est un diagramme maison, mais qui vaut ce qu'il vaut...

    Donc... place à la réflexion!

    Je vais réfléchir encore aux conseils de Luc, et puis je vous montrerai mes propositions demain...

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par poukill
    3) Certains attributs sont placés dans des classes alors qu'ils n'en font parti que pour l'implémentation (mais pas pour le rôle, cf Luc) Donc en gros, s'il est là, c'est pour m'arranger dans le code, alors qu'il faudrait penser objet pur, c'est à dire oublier le côté implémentation. Dur, dur... Ca me rappelle mes cours de java!
    Hum. Attention.
    C'est très bien d'avoir des attributs qui aident à l'implémentation. C'est un peu l'une de leurs raisons d'être premières.
    Ce que je voulais dire est différent.

    Ce qui me fait décider du design de mes classes, et en particulier de leur interface publique, ce sont les services qu'elles vont remplir (/rôles qu'elles vont tenir).
    Si pour réaliser (là, c'est l'implémentation) ces services j'ai besoin de données, je vais ensuite voir comment disposer de ces données. Là, il y a plein de façons.
    Ces données peuvent être obtenues va un autre objet qui va avoir la responsabilité de la fournir (donnée stockée, ou calculée) -- réduire le couplage, c'est aussi ne pas calculer soi-même ce qu'un autre est mieux à même de faire, cela évite de nécessiter des données de plus bas niveau dont on n'a que faire en fait.
    Ces données peuvent aussi être des attributs de l'objet courant que l'on stocke en local pour éviter d'aller les chercher au travers de 42 autres objets imbriqués.


    C'est assez difficile de parler avec des généralités comme je le fais, car il n'y a que des cas particuliers, et que je n'ai pas eu le temps d'approndir le cas particulier que tu as exposé. Chaque problème appelle à un design unique. (Des recettes peuvent toutes fois revenir, ce sont les Design Pattern.)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  16. #116
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par Luc Hermitte
    Si pour réaliser (là, c'est l'implémentation) ces services j'ai besoin de données, je vais ensuite voir comment disposer de ces données. Là, il y a plein de façons.
    Ces données peuvent être obtenues va un autre objet qui va avoir la responsabilité de la fournir (donnée stockée, ou calculée) -- réduire le couplage, c'est aussi ne pas calculer soi-même ce qu'un autre est mieux à même de faire, cela évite de nécessiter des données de plus bas niveau dont on n'a que faire en fait.
    Ces données peuvent aussi être des attributs de l'objet courant que l'on stocke en local pour éviter d'aller les chercher au travers de 42 autres objets imbriqués.
    OK d'accord, je pense avoir enfin compris! L'interface publique de la classe se décide à la conception. On lui attribue tel rôle, et à une autre classe tel autre. Si besoin est, on peut rajouter des attributs, par commodité (cf ta dernière remarque), ou par besoin.

    Lorsqu'on décide d'ajouter un attribut privé, il va falloir nécessairement rajouter une méthode (pardon, je sais que c'est un terme du java, mais c'est très clair comme ça dans ma tête, alors que fonction membre moins ).
    On pourrait déclarer cette méthode publique, dans ce cas, ça va modifier un poil l'interface publique de la classe (grave? pas grave?).
    La déclarer en privée va restreindre l'utilisation de celle-ci dans la classe même, donc en local.

    Si l'attribut en question n'est recopié que par commodité, alors pour moi il vaudrait mieux laisser private.
    Si c'est un attribut calculé ici, et donc devant être accessible par les autres classes, alors évidemment la méthode sera publique!

    Dites moi si je dis vrai, ou bien alors si je me suis planté au cours de ce raisonnement!

    MErci

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par poukill
    Lorsqu'on décide d'ajouter un attribut privé, il va falloir nécessairement rajouter une méthode
    Non. Quand j'ai des vecteurs dans mes classes, j'ai autre chose à faire que de rajouter des indirections et/ou encapsuler mes push_back. Même combat pour mes mutex, ... Ceci dit, parfois, il m'arrive de définir des accesseurs à accessiblité restreinte (protégés) juste pour montrer que je fais des accès en lecture seule sur tel ou tel attribut. C'est loin d'être systématique.

    On pourrait déclarer cette méthode publique, dans ce cas, ça va modifier un poil l'interface publique de la classe (grave? pas grave?).
    Grave. Un attribut n'est pas nécessairement une propriété. Si tu rajoutes un truc public, c'est pour rajouter un nouveau service, une nouvelle responsabilité. Ce qui faut se demander, c'est si c'est ajout a du sens ou non. En fonction de cela => public ou pas.

    La déclarer en privée va restreindre l'utilisation de celle-ci dans la classe même, donc en local.
    Tout à fait. C'est tout le principe de "attribut qui sert à l'implémentation", "détail d'implémentation", ...

    Si l'attribut en question n'est recopié que par commodité, alors pour moi il vaudrait mieux laisser private.
    Euh .. Oui.

    Si c'est un attribut calculé ici, et donc devant être accessible par les autres classes, alors évidemment la méthode sera publique!
    Pourquoi "donc" ? Les calculs intermédiaires que tu réalises ne font pas nécessairement parti des services que tu rends. Le maçon ne va pas te laisser la truelle quand il a fini, ni le béton qu'il a gaché et qui n'a pas été utilisé. Les deux sont des données qui servent à l'implémentation, la seconde est calculé. Et le service, c'est monter les agglos.


    Tout cela me fait penser au point de FAQ sur les accesseurs. En particulier le distingo attribut (donnée d'implémentation) <-> propriété (donnée exposée via l'interface publique généralisée)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  18. #118
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Citation Envoyé par Luc Hermitte
    C'est le genre de cas où la fonction membre serait statique (car elle ne porte sur aucun objet en particulier) (-> fonction membre de classe). Ici, il me semble que c'est avant tout un artifice pour déclarer la fonction dans une portée, pas pour dire que les fonctions membres des objets (!= classe) peuvent être implémentées à l'aide de fonctions, dans la même thématique, mais qui ne portent sur aucun objet en particulier.
    Bref, j'utiliserai un espace de noms. En plus, c'est extensible.
    Je dois avouer que je n'ai pas tout compris.
    Un espace de noms? Je ne vois pas pour l'instant l'intérêt. Pour l'instant, je n'ai fait que les utiliser, mais je n'en ai jamais créé !

    Citation Envoyé par Luc Hermitte
    Grave. Un attribut n'est pas nécessairement une propriété. Si tu rajoutes un truc public, c'est pour rajouter un nouveau service, une nouvelle responsabilité. Ce qui faut se demander, c'est si c'est ajout a du sens ou non. En fonction de cela => public ou pas.
    Oui d'accord. C'est finalement très logique. Une fois que l'on a bien en tête qui fait quoi, celà devient relativement facile à écrire!

    J'écris régulièrement des classes sans données. Parce que le pattern stratégie ne requiert pas nécessairement la présence d'une donnée -- je spécialise des comportements en fonction de la stratégie courante (qui se substitue à une classe qui décrit de manière assez "abstraite" le traitement à réaliser). Parce que parfois en méta-prog j'ai besoin de classes particulières polices, traits ou autres qui ne définissent que des types ou des fonctions.
    Ceci m'amène à une nouvelle question assez générale : celle du couplage entre classes. Admettons que je crée d'autres classes. Apparemment, il vaut mieux créer plus de classes, et ainsi minimiser les couplages entre elles, que de rattacher à tout prix des fonctions ou attribut faisant moyennement parti des classes déjà existantes!
    Question : est-ce que le design des classes est mauvais si l'ordre de création des classes depuis la classe principale est important?

    Exemple : Ma classe Choc est la classe principale, base du programme.

    Voici la déclaration de son constructeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Choc::Choc(int num_choc, std::string nom_cfp) 
    :numero_choc(num_choc), Camera(num_choc, nom_cfp), Ecran(), ...
    {
    	std::cout << "Choc numero " << num_choc << "cree" <<std::endl ;
    }
    En rouge, la partie qui coince pour moi... En effet, il est par exemple possible que Camera aie besoin d'Ecran, car dans son constructeur, je fais appel à camera.getLargeurEcran().
    Question donc: Parmis ces deux solutions, laquelle est "bonne":

    1) Mes constructeurs sont très complets, et remplissent tous les attributs privés du premier coup (et pas par 0 ou NULL). Dans ce cas, ils vont avoir besoin d'info chez d'autres classes (mieux placés pour contenir l'info) via une méthode publique...
    Problème : il faut que la classe qui détinet l'info en question soit déjà crée.

    2) Mes constructeurs de classes ne remplissent que les champs qu'ils sont sûr de connaître, et on remplit ensuite gentillement au fur et à mesure ce qu'il manque via méthodes...

    J'espère avoir été clair!

    Merci beaucoup!

  19. #119
    Membre Expert
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Par défaut
    Je me demandais... Je suis toujours parti sur :
    * de l'héritage
    * de la composition
    pour créer mon diagramme des classes

    Alors voilà : une classe seule (c'est à dire qui n'utilise pas d'héritage et où aucunes autres classes ne l'utilisent par composition) est-elle une abérration?

    Je me pose la question puisque :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    class CFP {
    
    	friend ajusterTailleVisibleEtIR();
    
    public:
    	CFP(int num_choc, std::string nom_cfp);
    	~CFP();
    
    	CImg <unsigned short> getImageIR();
        virtual setImageIR(CImg <unsigned short>);
    
    	CImg <unsigned short> getImageVisible();
    	setImageVisible();
    
    	CImg <unsigned short> warping();
    
    	std::string getNomComposant();
    	setNomComposant(std::string);
    
    	virtual setZone(int);
    	int getZone();
    
    	affichageMix(float, bool, float, bool);
    
    
    private:
    	PDC pdc;
    	CImg <unsigned short> image_IR;
    	CImg <unsigned short> image_visible;
    	CImg <>champ_deformation;
    	std::string nom_composant;
    	int zone;
    	int numero_choc;
    	float coeff_mul;
    
    }
    PDC pourrait être retiré de cette classe. Ainsi ma classe PDC serait sans liens avec les autres classes. Mais elle possederait des méthodes pour interagir avec les autres...

    Y a t-il une règle générale à suivre dans mon cas?

    Merci

    Poukill, qui pose et se pose bcp de questions !

  20. #120
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Est-ce que la classe CFP a besoin d'une instance de PDC ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 6 sur 12 PremièrePremière ... 2345678910 ... DernièreDernière

Discussions similaires

  1. Réponses: 7
    Dernier message: 01/01/2010, 08h31
  2. [POO] d’encapsulation des classe
    Par amazircool dans le forum Langage
    Réponses: 6
    Dernier message: 17/09/2007, 18h33
  3. [POO] Héritage des classes
    Par mic79 dans le forum Langage
    Réponses: 27
    Dernier message: 09/03/2007, 20h02
  4. [POO] Organisation des classes PHP
    Par AsQuel dans le forum Langage
    Réponses: 6
    Dernier message: 16/02/2007, 09h09
  5. [POO] faire des classes en php
    Par gromit83 dans le forum Langage
    Réponses: 2
    Dernier message: 13/04/2006, 16h10

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