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 :

héritage et chaine d'objets


Sujet :

C++

  1. #21
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 963
    Points
    32 963
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    ??

    Les données ne sont pas copiés systématiquement dans leu jeu. Elles sont copiés lorsque c'est nécessaire ( a la création de l'objet, par ex ). Donc quand un objet veut savoir ce qui se passe dans un autre, il va simplement voir à son adresse, d'où les pointeurs. Il peut ainsi avoir, par ex, ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    protected :
     
       std::shared_ptr < OBJECT > _target ;
    et l'utiliser ainsi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    void OBJECT_Healer::folow()
    {
       _physics.setDestination ( _target -> getPhysics().getPosition() ) ;
    }
    Un shared_ptr ça reste de la copie.
    Un objet qui en suit un autre n'a, sauf exception maitrisée - ce qui n'est amha clairement pas ton cas -, absolument pas à incider sur la durée de vie de l'objet suivi. Donc le shared_ptr est une hérésie. Si tu veux utiliser un smart pointer, c'est un weak_ptr qu'il convient d'utiliser.
    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.

  2. #22
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    hola hola, molo svp, je suis débutant...

    Un shared_ptr ça reste de la copie.
    ??
    de la copie, mais d'un pointeur ( un peu amélioré, certe, mais pointeur tout de même ), donc une simple adresse ?

    Et pour la durée de vie de l'objet, il faut voir qu'elle est gérée avant tout dans le "moteur". Donc si un objet détient un pointeur d'un autre objet, a la limite, il aura simplement a vérifier ci celui-ci est toujours vivant avant de l'utiliser, et le reset si ce n'est pas le cas. Quoi qu'il en soit, la durée de vie de l'objet ne le concerne pas...N'est ce pas l’intérêt des shared_ptr ? d'éviter de s'embêter avec ca ?

  3. #23
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 045
    Points : 11 368
    Points
    11 368
    Billets dans le blog
    10
    Par défaut
    Non, le shared_ptr te permet de dire que la responsabilite de la duree de vie de ton pointeur peut etre partagee.
    Cependant c'est une mauvaise idee de se dire que tu vas partager cette duree de vie, ne serait-ce que pour le determinisme de ton application.
    Il vaut mieux avoir UN shared_ptr et PLUSIEURS weak_ptr sur ce shared_ptr. Ainsi TU maitrises la duree de vie de ton pointeur.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  4. #24
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    Ok, merci pour ces conseils, je vais veiller à les appliquer.

  5. #25
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Puisque la discussion est résolue, je me permet de venir polluer sans vergogne
    Citation Envoyé par dragonjoker59 Voir le message
    Il vaut mieux avoir UN shared_ptr et PLUSIEURS weak_ptr sur ce shared_ptr. Ainsi TU maitrises la duree de vie de ton pointeur.
    Cette assertion est sujette à débat. L'avantage d'un shared_ptr est justement de ne pas se préoccuper de la responsabilité. J'ai rencontré quelques cas où l'utilisation de shared_ptr simplifiait tellement l'architecture que ça en devenait une justification valide à mes yeux, même si, structurellement, c'est toujours gênant d'avoir des objets "libres" (dans le sens de l'agrégation/composition: ils n'ont pas de propriétaires).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    Citation Envoyé par r0d Voir le message
    Puisque la discussion est résolue, je me permet de venir polluer sans vergogne
    Ben, du coup, moi aussi
    Cette assertion est sujette à débat. L'avantage d'un shared_ptr est justement de ne pas se préoccuper de la responsabilité. J'ai rencontré quelques cas où l'utilisation de shared_ptr simplifiait tellement l'architecture que ça en devenait une justification valide à mes yeux, même si, structurellement, c'est toujours gênant d'avoir des objets "libres" (dans le sens de l'agrégation/composition: ils n'ont pas de propriétaires).
    As-tu déjà croisé une seule fonctionnalité, un seul principe, une seule notion permettant de faire une assertion qui ne soit pas sujette à débat

    Quel que soit le domaine concerné, il y aura toujours des "cas particuliers" sur lesquels il est possible de débattre des heures, surtout en C++ . Bien sur, il y aura toujours des cas -- vu que c'est le sujet ici -- où le fait de partager la responsabilité de la durée de vie d'un pointeur pourront s'avérer être "la moins mauvaise" solution (à défaut d'être la meilleure ). Mais il faut savoir que cela a un prix et que c'est justement ce prix qui devrait nous inciter à ne partir vers cette solution que "si l'on n'a pas d'autre choix".

    Je n'ai pas lu toute la discussion, mais j'ai l'impression qu'il reste un très sérieux problème de non respect du SRP dans tout le code que j'ai aperçu. Je crois donc très sincèrement que, si mazertys17 arrivait à définir des responsabilités claire et uniques pour ses différents classes, le besoin des shared_ptr dans son ensemble disparaitrait pour ainsi dire de lui-même

    Ceci dit, encore une fois, tu n'as pas tord du tout et tu as eu tout à fait raison -- ne serait-ce que dans un soucis d'être complet -- de préciser qu'il faut jamais dire jamais
    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

  7. #27
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    définir des responsabilités claire et uniques pour ses différents classes, le besoin des shared_ptr dans son ensemble disparaitrait pour ainsi dire de lui-même
    Etant donné que j'utilise l'Héritage, le pointeur devient nécessaire, non ?
    Donc le shared_ptr est justifié ?

    Si vous voulez m'aider, je vais vous montrer ici, grosso modo comment fonctionne mon programme, jusqu'à présent :

    une class Engine, va charger les objets nécessaires à la scène depuis une class Ressource, qui va les construire puis les cloner en shared_ptr ( en gardant un modèle sous la main si on lui redemandait l'objet). l'Engine les mets alors dans un container.

    Chaque objet à accès à une class System, qui va avoir pour rôle de gérer les collisions et l'affichage, et de partager certaines infos ( comme la vue du jeu, position de la souris sur le world etc...).

    les Objects sont "polymorphiques", mais ils contiennent tous les 4 même class : Graphics, Physics, State et Sound, sachant que le Physics a accès au Graphics ( avec un ptr ) et au State, et que le State à accès au Graphics.

    ex :- le State perd de la vie, il l'indique au graphics qui change l'aspect de l'objet.
    - le physics entre en collision avec un objet, il l'indique au State, qui change la vie, l'indiquant ainsi au graphics.

    Chaque objet envoi donc automatiquement au System ses différentes infos, dans leur plus petit "état" possible, à savoir une Collision et une IE, par ex.

    Apparemment, cela ne semble pas respecter le "SRP" ( dont je n'ai pas encore tout compris ). Mais en faisant ainsi, je pensais optimiser un peut les choses en faisant en sorte que les informations soient traités au plus bas niveau possible.

    Est-ce cohérent selon vous ?

  8. #28
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Salut Koala, ça faisait longtemps!
    Toujours un plaisir de te lire

    Citation Envoyé par koala01 Voir le message
    As-tu déjà croisé une seule fonctionnalité, un seul principe, une seule notion permettant de faire une assertion qui ne soit pas sujette à débat
    Non, effectivement. Et c'est une des raisons pour lesquelles le C++ est mon langage préféré. J'ai même eu récemment une discussion passionnante avec un étrange développeur qui utilisait, à un endroit dans son code, un void*, et qui est parvenu, après une longue et âpre joute verbale, à me convaincre que dans ce cas, c'était effectivement la meilleure solution (il s'agissait de traitement de buffer audio au niveau du driver).

    Citation Envoyé par koala01 Voir le message
    Mais il faut savoir que cela a un prix et que c'est justement ce prix qui devrait nous inciter à ne partir vers cette solution que "si l'on n'a pas d'autre choix".
    Oui, mais tout a un prix. A partir du moment où on a écrit main(), tout ce qui suit a un coût

    Depuis quelques mois je travaille sur de l'optimisation de code c# (on ne fait presque plus rien en c++ dans ma boite ). Ne rigoles pas, non seulement c'est absolument passionnant, mais en plus le c# peut être extrêmement rapide si on fait bien les choses. On approche même les performances de C et de C++ sur certaines choses. Enfin bref, je dis ça parce que je l'optimisation en C# (qui est un langage très haut niveau), ne se fait pas en insérant des morceaux d'assembleur, mais en modifiant le design pour profiter au mieux des optimisations du compilateur et des spécificités du langage. Et du coup, je suis constamment contraint à des choix cornéliens, parce que souvent, les optimisations vont à l'encontre de la maintenabilité. Je dois donc constamment jongler entre maintenabilité et performances, et parfois j'arrive à des conclusions étranges, dans le but de garder cet équilibre entre performances et design, comme par exemple de laisser le GAC faire le job, ce que je considérais comme une forme de terrorisme il n'y a ne serait-ce que quelques mois.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    Etant donné que j'utilise l'Héritage, le pointeur devient nécessaire, non ?
    Il y a des chances que le recours aux pointeurs et à l'allocation dynamique soit nécessaire, mais
    Donc le shared_ptr est justifié ?
    Non, absolument pas...

    L'utilisation des shared_ptr n'est justifiée que quand tu n'arrives pas à déterminer "qui est responsable de la durée de vie" de ton pointeur. Dans de très nombreuses circonstance, le fait que tu n'arrives pas à le déterminer tend au contraire à prouver qu'il est très certainement utile de revoir ta conception afin de donner cette responsabilité à une et une seule classe (et sans doute d'ailleurs à une classe qui n'existera que sous une forme d'instance strictement unique)

    Toutes les autres classes qui font éventuellement référence (d'une manière ou d'une autre) à tes pointeurs peuvent alors être considérées comme "des utilisateurs tout ce qu'il y a de plus simple".

    Si vous voulez m'aider, je vais vous montrer ici, grosso modo comment fonctionne mon programme, jusqu'à présent :

    une class Engine, va charger les objets nécessaires à la scène depuis une class Ressource, qui va les construire puis les cloner en shared_ptr ( en gardant un modèle sous la main si on lui redemandait l'objet). l'Engine les mets alors dans un container.
    Déjà sur cette phrase, on se rend compte que le principe de la responsabilité unique (SRP) n'est pas respecté ... L'engine doit effectivement garder en mémoire les objets nécessaires à la scène, mais ce n'est absolument pas à lui de charger ces objets, ni même de les créer:
    Le chargement des données modélisant les différents objets (fichier *obj, sans doute) devrait être délégué à une classe qui ne s'occuperait que de cela (ObjLoader, par exemple ) et il en irait de même pour la création des objets de la scène, qui devrait être prise en charge par une classe distincte (ObjectFactory, par exemple) qui maintiendrait le modèle de l'objet (ce qui a été chargé par ObjLoader) et qui pourrait l'utiliser pour créer un objet d'un type particulier, qu'elle renverrait sous la forme d'un pointeur (intelligent, de préférence) sur un objet "général" (sur ta classe de base, autrement dit )

    La question est : pourquoi un shared_ptr... De prime abord, le seul responsable de la durée de vie des objets créés est sans doute enginge (ou peut être une classe qui trainerait et qui s'occuperait du niveau ou du terrain de jeu ???). Toutes tes autres classes ne sont que des utilisateurs de tes pointeurs

    Chaque objet à accès à une class System, qui va avoir pour rôle de gérer les collisions et l'affichage, et de partager certaines infos ( comme la vue du jeu, position de la souris sur le world etc...).
    Encore une fois, il y a un gros problème de responsabilité, car, si je compte bien :
    1. gérer les collections
    2. gérer l'affichage
    3. partager certaines informations
    Ca fait... trois responsabilités... Autrement dit, cela en fait deux de trop

    De plus, pourquoi chaque objet devrait il avoir accès à la classe System A mon sens, ce serait plutôt le système (ou plutôt : différents types de systèmes, engine pouvant être considéré comme l'un deux avec la responsabilité particuière de devoir s'occuper de la durée de vie des pointeurs ) qui devrait accéder aux différents objets, non l'inverse
    les Objects sont "polymorphiques", mais ils contiennent tous les 4 même class : Graphics, Physics, State et Sound, sachant que le Physics a accès au Graphics ( avec un ptr ) et au State, et que le State à accès au Graphics.
    Pourquoi doivent-ils se balader avec tout cela

    Si tu as Graphics, Physics, State et Sound, cela correspond à ... quatre modules qui devraient pouvoir travailler de manière indépendante : A l'extrème limite, tu devrait pouvoir développer l'intégralité du module "graphics" (ou n'importe quel autre) sans avoir besoin d'aucun des autres!!! Ce sont des choses réellement tout à fait séparées!

    Il n'y a donc aucune raison pour exposer les besoin de ces quatre modules dans une sorte de "module central" quelconque. Tout ce qu'il faut, c'est la possibilité de "faire le lien" entre un fichier audio (par exemple) et le fichier qui l'utilise. Et plus la donnée sera simple, plus la recherche sera facile. Du coup, un size_t dont le numéro identifie de manière unique et non ambigue chaque fichier audio (chaque élément de physique, chaque partie devant être affichée) correspond à tout ce qu'il te faut au niveau de tes objets
    ex :- le State perd de la vie, il l'indique au graphics qui change l'aspect de l'objet.
    - le physics entre en collision avec un objet, il l'indique au State, qui change la vie, l'indiquant ainsi au graphics.
    Surement pas : le sytème de physique (je n'aime pas ce terme, car trop générique, mais bon) se rend contre que deux objets entre en collision : il envoit un message "collision avec (l'autre objet) aux deux objets en présence.

    Chacun de ces deux objets émet alors un signal "collision" qui sera récupéré par le système d'affichage, celui du son et celui d'état et chacun réagira à sa propre manière :
    le système d'affichage en affichant une "explosion"
    le système de son en faisant entre "boum"
    le système d'état en influençant sur la vie des objet ayant émis le signal

    Ca ne te parrait pas plus "logique"
    Chaque objet envoi donc automatiquement au System ses différentes infos, dans leur plus petit "état" possible, à savoir une Collision et une IE, par ex.
    Tes objets doivent rester les plus simples possibles, surtout au niveau de la partie "business" (métier, si tu préfère): des données rudimentaires (des type primtifis de préférences, des structures simples si tu n'a pas le choix) et la possibilité d'émettre et de recevoir quelques signaux, et c'est tout
    Apparemment, cela ne semble pas respecter le "SRP" ( dont je n'ai pas encore tout compris ).
    Ce n'est en effet clairement pas le cas

    SRP signifie Single Responsability Principle (ou, si tu préfères, principe de la responsabilité unique) Et il est finalement simple à comprendre : si tu veux pouvoir faire évoluer facilement ton projet, chaque classe, chaque fonction ne doit s'occuper que de faire une seule et unique chose. Cela t'apporte énormément d'avantages, parmi lesquels on peut citer:
    • des petites fonctions, de petites classes de peu de lignes (instructions) ==> facile à lire et à comprendre
    • des petits comportements tout simples que l'on peut utiliser ensemble dans de très nombreuses combinaisons ==> tu rajoute un "cas particulier sans aucun problème"
    • Des petits comportements, ca fait peu de variable et c'est facile à tester ==> tu as beaucoup plus facile à "prouver" que ta fonction fait ce qu'elle est sensée faire
    • j'en passe et de meilleures...

    Mais en faisant ainsi, je pensais optimiser un peut les choses en faisant en sorte que les informations soient traités au plus bas niveau possible.
    N'essaye pas d'optimiser maintenant... Donald Knuth disait
    Citation Envoyé par Donald Knuth
    premature optimization is the root of all evil
    Cela pourrait se traduire par quelque chose comme "l'optimisation prématurée est le chemin vers l'enfer". Et il a raison. Commence par avoir un code facile à lire et à comprendre, même s'il ne fait pas forcément ce qu'on attend de lui.

    Mais, comme il sera facile à lire et à comprendre, tu auras facile à le corriger pour qu'il réagisse exactement de la manière dont on est en droit de s'y attendre et donc d'atteindre la deuxième étape :

    Commence par avoir un code qui fait exactement ce que tu attends de sa part, même s'il n'est pas forcément le plus efficace : un code qui fonctionne lentement est utilisable, même s'il met la patience de l'utilisateur à rude épreuve... Mais un code qui "plante rapidement" ne l'est pas du tout, et tend à énerver beaucoup plus l'utilisateur

    Une fois que tu as tout cela, tu peux passer à la troisième étape : avoir un code qui fait rapidement ce que l'on attend de lui...
    La priorité consistera à déterminer "où ca coince", mais, pour cela, il faut que ca fonctionne :

    Une fois que tu sais où ca coince, il faut déterminer pourquoi:
    • Selon l'utilisation qui est faite des données, certains types de collections s'avèrent beaucoup plus rapides que d'autres. Certains algorithmes tendent aussi parfois à relier Bruxelles à Paris en passant par Moscou, Vladivostock et Londres... Si on peut éviter ces détours, on ne s'en sent généralement que mieux
    • Parfois, un test qui évitera un traitement lourd fera gagner énormément de performances, surtout si ce test lourd est effectué souvent


    Est-ce cohérent selon vous ?
    Heu, je crois que toute ma réponse te permet de répondre par toi meme à cette question non
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #30
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Citation Envoyé par koala01 Voir le message
    L'utilisation des shared_ptr n'est justifiée que quand tu n'arrives pas à déterminer "qui est responsable de la durée de vie" de ton pointeur.
    C'est un point sur lequel je ne suis pas d'accord. Pour moi :
    • l’unicité de l'ownership et l'utilisation de shared_ptr sont de problèmes transverses (comme l'a dit dragonjoker59, on peut avoir 1 shared et plusieurs weak, ce qui correspond a avoir un seul responsable (permanent)) ;
    • du fait de la sécurité apportée par shared_ptr, il peut/doit l'utiliser même lorsque l'on a qu'un seul ownership (en particulier en multi-thread).


    Un simple vector<unique_ptr> peut poser problème. Si on veut conserver un "lien" vers un objet managé par ce vector :
    • soit on conserve un "lien" vers le vector et on redemande a chaque fois l’accès a l'objet ;
    • soit on conserve un iterator, mais il peut être invalidé ;
    • soit on conserve une référence sur un unique_ptr, mais elle peut être invalidée ;
    • soit on conserve un pointeur nu vers l'objet, mais on ne peut pas vérifier les dangling pointeurs ;
    • soit on utilise un shared + weak.


    Le shared est celui qui apporte le maximum de garanties dans ces conditions, c'est ce que je recommanderais, alors que l'on a bien qu'un seul ownership

  11. #31
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    wouaille.

    je crois que j'ai encore du boulot !

    mais bon j'ai déjà du faire un peu de progrès : je me suis mal exprimé sur la facon de gérer les ressources :

    L'engine doit effectivement garder en mémoire les objets nécessaires à la scène, mais ce n'est absolument pas à lui de charger ces objets, ni même de les créer:
    En effet, et ce n'est pas ce que je fais : c'est la class "Resources" qui se charge de créer, stocker et copier l'objet. L'Engine ne fait que le récupérer et le ranger dans son container....

    Encore une fois, il y a un gros problème de responsabilité, car, si je compte bien :
    gérer les collections collisions
    gérer l'affichage
    partager certaines informations
    Ca fait... trois responsabilités... Autrement dit, cela en fait deux de trop
    Oui, là...pour changer ca faudrait que je revois ma conception...

    Pourquoi doivent-ils se balader avec tout cela
    ( il s'agit des class Physics, Graphics, State et Sound ).

    Bah question pratique, je me disais :

    -pour éviter de s’emmêler les pinceaux, entre par exemple, la position d'une image, (le graphics ) et la position de l'objet réel ( physic), qui n'est pas forcément la même.

    -pour automatiser au max la gestion des objets : le physics prend un damage, il l'indique au State, qui note le changement et l'indique au Graphics...Si l'objet doit devenir vert, alors c'est indiqué dans son graphis dès le chargement...plutôt que d'allourdir l'objet en le chargeant d'informations...

    -et surtout pour qu'un objet hérité "Object_Ctr_Unit_SuperMegaKiller", puisse donner son "physics" à un simple "Object"...puisque les deux contiennent le même "Physics".


    Chacun de ces deux objets émet alors un signal "collision" qui sera récupéré par le système d'affichage, celui du son et celui d'état et chacun réagira à sa propre manière :
    Ca revient un peu a ca non ? mon Graphic est le système d'affichage, Sound, celui du son etc..

    En tout cas, merci pour les conseils, je vais bien relire, et tenter d'en tirer le maxi

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par mintho carmo Voir le message
    C'est un point sur lequel je ne suis pas d'accord. Pour moi :
    • l’unicité de l'ownership et l'utilisation de shared_ptr sont de problèmes transverses (comme l'a dit dragonjoker59, on peut avoir 1 shared et plusieurs weak, ce qui correspond a avoir un seul responsable (permanent)) ;
    • du fait de la sécurité apportée par shared_ptr, il peut/doit l'utiliser même lorsque l'on a qu'un seul ownership (en particulier en multi-thread).
    Tant que tu n'auras pas "un autre" shared_ptr que celui qui se trouve dans ton "responsable unique permanent", le principe même de shared_ptr ne t'apportera absolument aucune garantie, que ce soit en environnement mono-thread ou multi-threadé : le shared_ptr ne s'intéresse qu'à l'existence d'un autre shared_ptr sur le même objet pour décider (ou non) de sa destruction. En aucun cas, il ne s'intéresse à la présence d'éventuels weak_ptr pour savoir s'il peut, oui ou non, décider de détruire l'objet.

    L'utilisation de weak_ptr ne fera que te donner le sentiment que tu travailles proprement en t'obligeant à vérifier s'il est toujours valide (forcément, on ne sait pas si l'objet sous-jacent a été détruit avant de l'avoir testé ) et, dans un environnement multi-thread, le problème reste toujours le même : que se passe-t-il si "thread1" vérifie si l'objet représenté par ton weak_ptr est toujours valide et que "thead2" décide de le détruire tout de suite après, mais avant que "thread1 n'ait essayé d'y accéder pour son traitement spécifique

    Un simple vector<unique_ptr> peut poser problème. Si on veut conserver un "lien" vers un objet managé par ce vector :
    • soit on conserve un "lien" vers le vector et on redemande a chaque fois l’accès a l'objet ;
    • soit on conserve un iterator, mais il peut être invalidé ;
    • soit on conserve une référence sur un unique_ptr, mais elle peut être invalidée ;
    • soit on conserve un pointeur nu vers l'objet, mais on ne peut pas vérifier les dangling pointeurs ;
    • soit on utilise un shared + weak.
    Tu oublies le principal :
    • Soit on veille à ce que les "liens" vers les pointeurs aient une durée de vie inférieure à celles des pointeurs intelligents.

    Et cette solution (on peut très bien envisager d'utiliser des std::reference_wrapper, pour ne pas s'inquiéter du problème des pointeurs ) sera toujours valide quoi qu'il arrive
    Le shared est celui qui apporte le maximum de garanties dans ces conditions, c'est ce que je recommanderais, alors que l'on a bien qu'un seul ownership
    Comme je viens de le dire, cela n'apporte absolument aucune garantie dans le cas d'une propriété non partagée. Le principe de base reste donc toujours le même :

    un seul propriétaire / responsable du moment où l'objet est détruit (c'est à dire la majorité des cas, si l'on s'y prend correctement) : unique_ptr
    Si impossible de déterminer un propriétaire / responsable du moment où l'objet est détruit : shared_ptr pour tous les propriétaires / responsables, weak_ptr pour faire le lien.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  13. #33
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut
    un seul propriétaire / responsable du moment où l'objet est détruit (c'est à dire la majorité des cas, si l'on s'y prend correctement) : unique_ptr
    mais dans le cas d'un STR, par exemple ( jeu de stratégie temps réel ), si un objet est la cible de plusieurs objets, comme c'est souvent le cas, il va falloir que tous les objets qui le ciblent aient accès à l'objet ciblé, pour savoir, par ex, sa vie, sa vitesse, et plus bêtement sa position...Peut-on faire ca avec un unique_ptr ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    wouaille.

    je crois que j'ai encore du boulot !

    mais bon j'ai déjà du faire un peu de progrès : je me suis mal exprimé sur la facon de gérer les ressources :



    En effet, et ce n'est pas ce que je fais : c'est la class "Resources" qui se charge de créer, stocker et copier l'objet. L'Engine ne fait que le récupérer et le ranger dans son container....
    Ah, ca me rassure Veille juste à utiliser des noms explicites... Pour moi, Engine représente une classe qui va mettre différent système (son, affichage, physique, ...) en commun pour proposer une interface permettant de jouer (en gros, elle viendrait "juste en dessous" de la classe Game ) et "Ressource" correspond à un terme que j'aurais utilisé pour... représenter différents types de ressources (ex : des textures, des sons, des sprites, ...)

    Plus tu arriveras à choisir des noms qui expriment exactement le but poursuivi par tes classes/ variables / fonctions, plus ton code sera facile à lire et, surtout, à comprendre. Nommer, c'est créer dit on. Si tu nomme une fouchette cuiller, les gens ne comprendront pas pourquoi tu t'évertue à demander une cuiller alors qu'on vient de t'en fournir une

    Oui, là...pour changer ca faudrait que je revois ma conception...
    Fais le le plus tot possible... Pour l'instant, cela ne devrait pas te prendre très longtemps ni impliquer trop de changements dans ton code... Mais plus tu tarderas, plus ton projet avancera, plus ce sera un changement difficile à mettre en place
    ( il s'agit des class Physics, Graphics, State et Sound ).
    Oui, oui, c'est bien d'elles que je parlais
    Bah question pratique, je me disais :
    -pour éviter de s’emmêler les pinceaux, entre par exemple, la position d'une image, (le graphics ) et la position de l'objet réel ( physic), qui n'est pas forcément la même.

    -pour automatiser au max la gestion des objets : le physics prend un damage, il l'indique au State, qui note le changement et l'indique au Graphics...Si l'objet doit devenir vert, alors c'est indiqué dans son graphis dès le chargement...plutôt que d'allourdir l'objet en le chargeant d'informations...

    -et surtout pour qu'un objet hérité "Object_Ctr_Unit_SuperMegaKiller", puisse donner son "physics" à un simple "Object"...puisque les deux contiennent le même "Physics".
    Et que penses-tu de l'approche....
    Citation Envoyé par bibi (ECS inside)
    Un objet, ce n'est qu'un identifiant unique (un size_t, c'est facile à comparer )
    Physics, Drawing, Sound, ... sont des composants que l'on peut associer à différents objets. Chaque "composant" étant manipulé par différent "systèmes", il suffit que je dispose de l'identifiant de l'objet pour savoir quel composant s'y rapproche. Si je ne trouve pas l'identifiant correspondant à un objet donné dans un de mes "systèmes", c'est que l'objet en question n'est pas sensé être manipulé par le système en question.

    Si le système physics se rend compte qu'il y a une collision entre, mettons, l'objet 12 356 et l'objet 34 559, il émet un signal "collision(12356,34559) vers un système particulier permettant spécifiquement de faire le lien entre les différents systèmes). Ce système spécialisé amplifie le signal et le réémet. Signal auquel sera connecté "tous les systèmes qui peuvent avoir quelque chose à faire en cas de collision" (comprends : le système son le système affichage, le système state, ...) et "chacune le traite de son coté" en sachant que les deux objets concernés sont l'objet 12356 (le vilain troll monstrueux) et l'objet 34559 (l'épée de glace de la reine gelée)
    Ca te semble pas plus cohérent comme approche

    Un size_t, c'est tout ce qu'il y a de plus basique comme type de donnée, c'est littéralement "passe partout" (et cela n'implique aucune interdépendance). Quant aux signaux émis et au slot qui s'y connectent, boost::signals2 fera particulièrement bien l'affaire

    Ca revient un peu a ca non ? mon Graphic est le système d'affichage, Sound, celui du son etc..
    Si ce sont tes systèmes que chaque objet se trimbale, c'est une raison de plus pour qu'ils ne le fassent pas
    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

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par mazertys17 Voir le message
    mais dans le cas d'un STR, par exemple ( jeu de stratégie temps réel ), si un objet est la cible de plusieurs objets, comme c'est souvent le cas, il va falloir que tous les objets qui le ciblent aient accès à l'objet ciblé, pour savoir, par ex, sa vie, sa vitesse,
    Héé non...

    Ils n'ont absolument pas à accéder directement à l'objet en question. Au pire, il posent la question au système qui se charge de la gestion des points de vie (ou de la vitesse ou de...) de l'ensemble des objets pour connaitre les caractéristiques de l'objet qui l'intéresse... Tu n'as donc absolument aucun besoin de shared_ptr pour ce genre de boulot

    et plus bêtement sa position...Peut-on faire ca avec un unique_ptr ?
    De toute évidence, le terme ECS (Entity Compount System pour entité / composant / système) te semble tout à fait étranger. Pourtant, cette approche te faciliterait grandement la vie, entre autres, en t'évitant d'avoir des hiérarchies de classes à rallonges et à charnières .

    Ceci dit, au risque de me répéter, aucun objet de ton jeu ne doit accéder directement à un autre objet. S'il s'interroge sur la caractéristique (quelle qu'elle soit) d'un autre objet, il s'adresse à la classe qui s'occupe de gérer cette caractéristique
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  16. #36
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 045
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 045
    Points : 11 368
    Points
    11 368
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par koala01 Voir le message
    L'utilisation de weak_ptr ne fera que te donner le sentiment que tu travailles proprement en t'obligeant à vérifier s'il est toujours valide (forcément, on ne sait pas si l'objet sous-jacent a été détruit avant de l'avoir testé ) et, dans un environnement multi-thread, le problème reste toujours le même : que se passe-t-il si "thread1" vérifie si l'objet représenté par ton weak_ptr est toujours valide et que "thead2" décide de le détruire tout de suite après, mais avant que "thread1 n'ait essayé d'y accéder pour son traitement spécifique
    Si tu rencontres ce genre de problèmes, c'est que tu utilises mal les weak_ptr.
    En fait on n'utilise pas la méthode weak_ptr<>::expired mais la méthode weak_ptr<>::lock qui a la bonne idée de locker l'objet de synchro (mutex ou autre) avant de te filer le shared_ptr...
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  17. #37
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    @koala01

    Je te rappelle que c'est une discussion que l'on a déjà eu

    Je reprends le problème a l'envers.

    Tu dis que l'on peut utiliser un reference_wrapper, il "suffit" de garantir que l'objet partage a une durée de vie plus grande que les pointeurs.

    Premièrement, si on pouvait toujours apporter cette garantie, on n'aurait jamais de problème de dangling pointer. C'est loin d’être le cas. (Peu importe que ce soit un problème de conception. Le problème existe)

    Je travaille avec des idiots (dont moi-même, dans quelques mois quand je relirais mon code). Ces idiots peuvent ne pas respecter cette contrainte sur la durée de vie de mon objet partagé. Je veux donc un moyen qui me permet (dans le thread qui utilise cet objet) de détecter une erreur dans le thread propriétaire. Quelle solution apporte quelle garantie ?

    - pointeur + reference_wrapper = dangling
    - unique + raw = dangling
    - unique + reference sur unique = n'empêche pas la destruction en cours d'utilisation de l'objet

    Le shared + weak évite le dangling. Et pour utiliser l'objet dans mon thread, je dois faire un lock, ce qui me permet de devenir propriétaire temporaire, le temps d'utilisation de l'objet, et donc garantir aussi que l'objet n'est pas détruit en cours d'utilisation.

    (On est d'accord que le shared dans le thread propriétaire ne va pas prendre en compte le weak s'il doit détruire l'objet. Mais peut importe, je ne recherche pas la garantie que l'objet n'est pas détruit avant de l'utiliser dans mon thread - si c’était le cas, on serait dans le cas de propriétaires multiples et on aurait plusieurs sahred - mais la garantie que s'il n'existe pas, je le saurais. L'autre garantie que je recherche - la non-destruction pendant utilisation - est apportée par le lock)

    On est d'accord qu'une bonne conception est la meilleure approche. Mais un code robuste permettra de vérifier si quelqu'un fait une erreur et ne respecte pas la conception. Sans cela, tu n'es pas a l'abris d'une erreur et ton code n'est pas robuste.

    Donc, je pense que shared apporte plus de garantie que unique et peut être utilisé aussi lorsque l'on a un propriétaire unique.

    Citation Envoyé par koala01 Voir le message
    que se passe-t-il si "thread1" vérifie si l'objet représenté par ton weak_ptr est toujours valide et que "thead2" décide de le détruire tout de suite après, mais avant que "thread1 n'ait essayé d'y accéder pour son traitement spécifique
    Comme je l'ai dit : lock.
    Utiliser un weak en faisant un expired puis un lock est une erreur d'utilisation de weak.

  18. #38
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    521
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 521
    Points : 136
    Points
    136
    Par défaut


    merci ! Ça a en effet l'air d'être clairement le niveau supérieur...

    Si je te suis bien, ça pourrait ressembler à ca :

    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
     
     
    void Engine::load()
    {
           _number ++ ;
     
           //là on charge les donnés depuis le disque, par exemple, 
           //et construit les modules demandé pour les mettre enssuite ds les systèmes :
     
           _drawing.add ( _number , _graphics ) ; //ou Graphics serait l'équivalent de ce que j'ai dit plus haut...
           _physics.add ( _number, _collision );
     
           //etc...
     
    }
     
    void Engine::update()
    {
           _drawing.update() ;
           _physics.update() ;
           _sound.update() ;
           //etc...
    }
    Suis-je sur la bonne piste ?

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par dragonjoker59 Voir le message
    Si tu rencontres ce genre de problèmes, c'est que tu utilises mal les weak_ptr.
    En fait on n'utilise pas la méthode weak_ptr<>::expired mais la méthode weak_ptr<>::lock qui a la bonne idée de locker l'objet de synchro (mutex ou autre) avant de te filer le shared_ptr...
    Malheureusement, ce serait trop beau!!! Tant que tu n'as qu'un seul weak_ptr, c'est le "seul maitre à bord" et lock fait appel à expired() pour savoir s'il renvoie un weak_ptr "vide" (dont le pointeur sous-jacent vaut nullptr) ou sur l'objet sous-jacent... Le problème reste donc strictement le même

    En un mot comme en cent : si tu n'as pas systématiquement deux co-responsables, ton utilisation de weak_ptr ne garantira absolument rien et c'est normal, vu que la décision de détruire l'objet sous-jacent ne devient partagée que... quand l'objet est partagé

    Tu tournes cela comme tu le veux : si tu sais à l'avance que tu as deux "co responsables" pour ton objet, ok, vas-y, utilises shared_ptr, c'est fait pour cela. Mais utiliser shared_ptr "pour le cas où" alors que tu as un propriétaire unique (ou sensé l'être), c'est du gaspillage de ressources.
    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

  20. #40
    Membre éclairé

    Profil pro
    Inscrit en
    Décembre 2013
    Messages
    393
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 393
    Points : 685
    Points
    685
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Malheureusement, ce serait trop beau!!! Tant que tu n'as qu'un seul weak_ptr, c'est le "seul maitre à bord" et lock fait appel à expired() pour savoir s'il renvoie un weak_ptr "vide" (dont le pointeur sous-jacent vaut nullptr) ou sur l'objet sous-jacent... Le problème reste donc strictement le même
    Je pense que tu te méprends sur weak_ptr. Lorsque tu fais un lock, tu obtiens un shared_ptr. Si ce shared_ptr est valide, cela veut dire que le premier shared_ptr (le propriétaire) n'a pas encore détruit l'objet. Et s'il souhaite ensuite le détruire, tu as un shared_ptr dessus, tu as donc la garantie que l'objet ne sera pas détruit tant que tu conserves ce shared_ptr.

    En bref, tu es sens utiliser un weak comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void f() {
        auto sp = wp.lock();
        if(sp) {
            // ici, tu utilises ton objet et tu es sur qu'il ne sera pas détruit pendant son utilisation
        } else {
            // l'objet est détruit, tu ne peux pas l'utiliser. Il faut créer un nouvel objet
        }
    }
    Ce code est safe en termes mémoire. Il n'y a pas d’équivalent safe avec une autre approche

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. Héritage et tableau d'objets
    Par Mindiell dans le forum C++
    Réponses: 17
    Dernier message: 08/01/2009, 07h24
  2. [POO] Decoupage de chaine et objet
    Par bobspike dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 27/06/2008, 15h32
  3. Problème d'héritage css (classe et objet)
    Par Askle dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 03/06/2007, 20h11
  4. Mal a la tete avec liste chainée d'objet
    Par Raton dans le forum C++
    Réponses: 23
    Dernier message: 03/08/2005, 22h13
  5. [Java] Héritage et flux d'Objet
    Par guejo dans le forum CORBA
    Réponses: 2
    Dernier message: 22/02/2005, 11h14

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