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] Suivez-vous le principe de substitution de Liskov ?


Sujet :

C++

  1. #1
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut [POO] Suivez-vous le principe de substitution de Liskov ?
    Bonjour,

    Dans un monde où la POO est employée à toutes les sauces, dont certaines sont mauvaises, on voit des principes essentiels de programmation orientée objet bafoués.

    L'un d'entre eux est le Principe de Substitution de Liskov (Liskov Substitution Principle, LSP).

    En quoi consiste-t-il ?

    Introduit en 1987[1] par Barbara Liskov, le principe de substitution de Liskov est, formellement, le suivant :
    Si une propriété P est vraie pour une instance x d'un type T, alors cette propriété P doit rester vraie pour tout instance y d'un sous-type de T
    où dans notre cas les sous-types de T sont les classes qui dérivent de T.

    Moins formellement, il s'agit en fait que l'on puisse remplacer dans un code source toute instance de type Mere par une instance d'un type Fille qui dérive de Mere sans altérer en quoique ce soit la caractère correct du programme.

    La question est donc : suivez-vous ce principe dans vos hiérarchies de classes C++ ? Que pensez-vous de ce principe ? Lui trouvez-vous une utilité ? (j'espère )

    [1] Voir : http://citeseer.ist.psu.edu/cache/pa...ov94family.pdf

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Avec la virtualité si on remplace les instances de type Mère par les instances de type Fille, en changeant rien d'autre, le programme aura très souvent un comportement différent.

  3. #3
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Oui bien sûr, c'est le principe même de polymorphisme. Mais le programme se comportera correctement, c'est ça l'idée.

    Il s'agit de garder un programme correct en interchangeant des types dans une hiérarchie, cf le 1er post.

    Parfois, lorsqu'une classe B ne devrait pas hériter d'une classe A mais dont elle hérite quand même, on se retrouve avec un programme incohérent. C'est plutôt répandu comme violation du LSP.

  4. #4
    Membre habitué Avatar de Kromagg
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2008
    Messages : 275
    Points : 198
    Points
    198
    Par défaut
    Je ne connaissais pas ce principe, enfin je l'utilise souvent, mais je ne savais pas que c'était un principe de la POO et qu'il avait un petit nom
    Maintenant est-ce que le programme va se comporter correctement, je pense que tout dépend de ce que l'on fait dans les classes filles. Il pourrait très bien se comporter correctement, mais ne donnera pas le résultat voulu.
    C'est dans ses rêves que l'homme trouve la liberté cela fut, est et restera la vérité! (John Keating - Le cercle des poètes disparus)

  5. #5
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Citation Envoyé par Naoss Voir le message
    Je ne connaissais pas ce principe, enfin je l'utilise souvent, mais je ne savais pas que c'était un principe de la POO et qu'il avait un petit nom
    Maintenant est-ce que le programme va se comporter correctement, je pense que tout dépend de ce que l'on fait dans les classes filles. Il pourrait très bien se comporter correctement, mais ne donnera pas le résultat voulu.
    Oui oui, mais le but c'est qu'en remplaçant on n'aboutisse pas à une situation incohérente dans le programme.

  6. #6
    Membre habitué Avatar de Kromagg
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2008
    Messages
    275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Août 2008
    Messages : 275
    Points : 198
    Points
    198
    Par défaut
    On ne peut pas le garantir alors, tout dépend de la finalité de la classe fille, ce qu'elle va gérer. Je prend l'exemple d'un flux avec une classe mère comme ceci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    class BaseStream
        {
        protected:
     
            /// Le flux est-il ouvert ?
            bool mOpen;
     
        public:
     
            /**
             * Constructeur par défaut.
             */
            BaseStream(void) {}
     
            /**
             * Destructeur.
             */
            virtual ~BaseStream(void) {}
     
            /**
             * Ouvre le stream.
             * @Param       _overWrite : mode d'ouverture du flux.
             * @Retour      True si l'ouverture à réussie, false sinon.
             */
            virtual bool open(bool _overWrite) = 0;
     
            /**
             * Lecture d'une portion des données du flux vers le buffer..
             * @Param               _buffer : buffer qui va contenir les données inscrite dans le flux.
             *                              _count : taille en bytes à lire dans le flux.
             * @Retour              Nombre de bytes lus.
             */
            virtual size_t read(char* _buffer, size_t _count) = 0;
     
            /**
             * Ecriture d'une portion des données du buffer vers le flux.
             * @Param               _buffer : buffer qui va contenir les données à inscrire dans le flux.
             *                              _count : taille en bytes à inscrire dans le flux.
             * @Retour              Nombre de bytes écris.
             */
            virtual size_t write(const char* _buffer, size_t _count) = 0;
     
            /**
             * Indique si la fin du flux est atteinte.
             * @Retour              True si c'est la fin, false sinon.
             */
            virtual bool isEndOfStream(void) const = 0;
     
            /**
             * Indique si le flux est ouvert.
             * @Retour      True s'il l'est, false sinon.
             */
            virtual bool isOpen(void) const = 0;
     
            /**
             * Ferme le flux.
             */
            virtual void close(void) = 0;
        };
    Maintenant 2 classes fille : DataStream et FileStream.
    Disons que FileStream est un flux charger de gérer un fichier (donc sur un disque physique) et DataStream est un flux contenant un ensemble de données gérer dans un buffer (en mémoire).
    Le but est de charger une ressource. Dans notre cas que la ressource soit présente sur le disque dur (fichier xml par exemple) ou en mémoire le résultat final sera le même, tout ce que l'on veut c'est charger une ressource, donc on peut dire ici que le programme devrait fonctionner correctement.
    C'est dans ses rêves que l'homme trouve la liberté cela fut, est et restera la vérité! (John Keating - Le cercle des poètes disparus)

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

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Points : 1 452
    Points
    1 452
    Par défaut
    Je le bafoue : j'exige des paramètres dans le constructeur ou une initialisation différente pour certaines classes dérivées -- éventuellement transtypées ensuite en classes de base.

    Mais je pense pas que je doive changer mon code

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

    Informations professionnelles :
    Activité : aucun

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

    J'essaie - généralement - de le respecter, et principalement lorsque j'essaye d'expliquer ce qu'est l'héritage.

    C'est la raison pour laquelle j'insiste sur la valeur "sémantique" des termes utilisés pour représenter deux classes pour lesquelles l'héritage est envisagé, en essayant d'inciter la personne à se poser la question de savoir "s'il est sémantiquement correct de dire que la classe B est réellement une 'amélioration' de la classe A, ou s'il s'agit d'un objet se contentant d'avoir les mêmes caractéristiques".

    Sémantiquement, parlant, il est effectivement correct de dire que "l'homme est un (animal) mammifère", alors que, effectivement, bien que les caractéristiques soient identique, il est impossible de prétendre qu'une pile (qui utilise, rappelons le, le principe LIFO) est une file (qui utilise, elle, le principe FIFO), ou vice-versa.

    Ceci n'empêchant nullement de trouver une "point sémantiquement commun" dans une autre classe que nous pourrions nommer "structure dynamique"

    De la même manière, et malgré les écueils qui risquent quasi immanquablement de se présenter, je n'ai aucune difficulté à admettre l'héritage multiple: il est sémantiquement correct de dire q'une turbo-génératrice est une génératrice, tout comme il est sémantiquement correct de dire que c'est un turbine
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    On pourrait pinailler sur le fait que Barbara Liskov a introduit une définition, et que l'on a tiré un principe de cet article. Mais ce n'est pas important.
    Citation Envoyé par Alp Voir le message
    Moins formellement, il s'agit en fait que l'on puisse remplacer dans un code source toute instance de type Mere par une instance d'un type Fille qui dérive de Mere sans altérer en quoique ce soit la caractère correct du programme.

    La question est donc : suivez-vous ce principe dans vos hiérarchies de classes C++ ? Que pensez-vous de ce principe ? Lui trouvez-vous une utilité ? (j'espère )
    J'estime que ce principe est essentiel. Souvent on voit des critiques du C++ parce qu'il permet l'héritage multiple et que personne ne sait s'en servir.
    La vérité est que l'héritage fut vendu pour de mauvaises raisons (i.e. importer du code), et que beaucoup en sont restés là -- et ne savent pas s'en servir (alors imaginez l'héritage multiple). Avec une bonne compréhension et un respect du LSP, l'essentiel des critiques faites à l'encontre de l'héritage multiple s'évanouissent.

    Autrement, si dans une hiérarchie je n'ai pas de substituabilité, je passe en héritage privé (merci le C++) et basta: j'ai ainsi importé du code sans avoir fragilisé mon système en permettant des substitutions qui n'ont pas de sens ou qui sont instables.

    NB: Il est difficile de ne pas rapprocher le LSP de la programmation par contrats. Cf l'article de Robert C. Martin où il explique le LSP en s'appuyant sur des carrés et des rectangles. Cf aussi le fait qu'une liste triée, n'est pas une liste. Sujet déjà bien abordé par ici
    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. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Il faut aussi faire attention aux invariants dans l'autre sens. Si tu as un Carré, sous-type d'un Rectangle, il ne faut pas qu'il soit possible de modifier l'objet par sa vue Rectangle de manière à ce que les invariants de Carré ne soient plus satisfaits.
    La solution évidente dans ce cas est d'avoir des objets immutables.

    J'utilise personnellement peu l'héritage et préfère les concepts. L'affinement de concepts est similaire à la dérivation.
    Mais lorsqu'on utilise les concepts, ce genre de propriétés est vraiment évident. D'autant plus qu'on ne manipule que des interfaces non-intrusives, et non pas des classes.
    Boost ftw

  11. #11
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    Ce principe n'est ni plus ni moins que la raison d'être des interfaces.
    C'est pour cela qu'on dit souvent «Préférez la composition à l'héritage».
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

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

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

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Citation Envoyé par Florian Goo Voir le message
    Ce principe n'est ni plus ni moins que la raison d'être des interfaces.
    C'est pour cela qu'on dit souvent «Préférez la composition à l'héritage».
    J'ai tendance à voir les interfaces comme des petites roulettes qui permettent d'apprendre à concevoir proprement sans s'en rendre compte. Et quand on est grand, on passe au pattern NVI

    Oui pour la deuxième affirmation si on restreint l'affirmation à l'héritage public. L'héritage privé convient parfaitement pour importer du code sans permettre d'être utilisable en place de (après tout nous sommes sur un forum C++ ; Java/C# en sont incapables, ruby a un autre mot clé pour, etc.). Le choix héritage privé / composition dépendant d'aspects liés au niveau de couplage acceptable, au type de fainéantise autorisée (après tout, c'est un héritage méconnu), ...
    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...

  13. #13
    Membre éclairé
    Avatar de Florian Goo
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    680
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    1) NVI, mmh ? Je vais aller voir ça

    2) Bien sûr , quand je parle d'héritage, je pense au sens POO strict. L'héritage privé est une autre façon d'écrire une composition (un prof, à l'époque, racontait même qu'en mémoire c'était strictement identique), mais ce n'est que de la syntaxe.
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

  14. #14
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    1) NVI= Non virtual interface. En rapide, ne pas rendre virtuelles les fonctions membres publiques qui devrait l'être mais préférer qu'elles appelent des fonctions membres protected qui elles le serront
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  15. #15
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Alp Voir le message
    La question est donc : suivez-vous ce principe dans vos
    hiérarchies de classes C++ ?
    Durant la conception, oui. A noter que j'ai tendance à séparer mentalement
    la conception de sa réalisation et que si la notion abstraite de hiérarchie
    de type va s'implémenter avec de la hiérarchie de classes et alors
    respecter ce principe, je ne m'interdit pas d'utiliser le mécanisme C++
    d'héritage pour autre chose -- auquel cas le principe pourrait ne pas être
    respecté (mais je n'ai pas de cas sous la main).


    Citation Envoyé par loufoque Voir le message
    J'utilise personnellement peu l'héritage et préfère
    les concepts.
    Je ne suis pas sûr de te comprendre.

    D'une part en ce qui concerne le sujet de la discussion, quand tu ajoutes:

    L'affinement de concepts est similaire à la dérivation.
    Tu sembles conscient qu'il y a bien derrière une même notion et donc que le
    principe de substitution devrait s'appliquer exactement de la même manière.


    Si tu écris cela d'une manière plus générale, je ne sais pas de quoi tu
    parles précisément: il ne me semble pas que j'ai à faire un choix entre les
    deux.


    Est-ce que tu veux dire que tu préfères le polymorphisme paramétrique au
    polymorphisme d'inclusion? Mais les concepts sont justement de mon point
    de vue un mécanisme de polymorphisme d'inclusion (d'où l'applicabilité du
    LSP).

    Est-ce que tu veux dire que tu préfères l'utilisation de mécanismes
    statiques aux mécanismes dynamiques? Quand j'ai le choix aussi, mais les
    mécanismes dynamiques sont plus généraux et on n'a pas toujours le choix.


    Citation Envoyé par Florian Goo Voir le message
    L'héritage privé est une autre façon d'écrire
    une composition (un prof, à l'époque, racontait même qu'en mémoire c'était
    strictement identique), mais ce n'est que de la syntaxe.
    Et comment est-ce que tu supplantes un membre virtuel avec de la
    composition? (Il y a au moins une autre différence, purement technique,
    qui fait qu'on peut utiliser l'un ou l'autre: l'ordre d'initialisation par
    rapport aux bases).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

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

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Tu sembles conscient qu'il y a bien derrière une même notion et donc que le
    principe de substitution devrait s'appliquer exactement de la même manière
    L'argument que je voulais placer c'est qu'avec les concepts, puisqu'on ne manipule que des interfaces et non des classes, ce principe paraît vraiment naturel.
    Boost ftw

  17. #17
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par loufoque Voir le message
    L'argument que je voulais placer c'est qu'avec les concepts, puisqu'on ne manipule que des interfaces et non des classes, ce principe paraît vraiment naturel.
    Les concepts sont plus qu'une interface, ils associent une sémantique à celle-ci. Si tu affines un concept sur une base purement syntaxique (présence des interfaces requises), tu as un problème et c'est celui que le LSP cherche justement à éviter.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

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

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Les concepts sont par défaut nominaux. Seuls les concepts automatiques sont implicites et se basent sur des propriétés structurelles comme la syntaxe.
    Enfin bref, je vois pas où tu veux en venir.
    Boost ftw

  19. #19
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Les concepts sont par défaut nominaux. Seuls les concepts automatiques sont implicites et se basent sur des propriétés structurelles comme la syntaxe.
    Enfin bref, je vois pas où tu veux en venir.
    L'affinement des concepts est une relation de sous-type. Les éléments sont les types du C++, les catégories les concepts -- le fait que les catégories soient nominales ou structurelles n'a aucun rapport avec le sujet.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

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

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Oui, rien de nouveau.
    Je ne vois toujours pas où tu veux en venir.
    Boost ftw

Discussions similaires

  1. Réponses: 4
    Dernier message: 28/10/2018, 22h24
  2. Réponses: 2
    Dernier message: 28/11/2008, 10h30
  3. [POO] Voulez vous confirmer ma compréhension ?
    Par coussini dans le forum Autres
    Réponses: 5
    Dernier message: 22/05/2008, 15h34
  4. Réponses: 9
    Dernier message: 06/06/2007, 14h18
  5. [POO] [debutant] Comment pourriez vous traduire ceci?
    Par pierrot10 dans le forum Langage
    Réponses: 1
    Dernier message: 20/09/2006, 22h56

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