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 :

GoingNative 2013 - Sean Parent - C++ Seasoning


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut GoingNative 2013 - Sean Parent - C++ Seasoning
    Sean Parent - C++ Seasoning
    GoingNative 2013

    La conférence de Sean Parent lors des GoingNative 2013 est disponible :


    Sean Parent propose trois objectifs à viser lors de l'écriture de code C++ :


    Pas de boucle brute

    Une boucle brute est une boucle dans une fonction qui fait plus que l'algorithme de la boucle lui-même.

    Ces boucles rendent la compréhension du code difficile, son analyse ardue, ce qui a pour conséquence de générer un code prompt à l'erreur, particulièrement dans les cas qui ne sont pas évidents, et dont les problèmes de performances sont difficiles à résoudre.

    Quelles solutions ?

    • Utilisez un algorithme existant, standard de préférence s'il est disponible.
    • S'il n'est pas disponible, écrivez-le en tant que fonction générale.
    • Il serait bénéfique que chacun essaye de contribuer à une bibliothèque (de préférence open-source) en soumettant au moins un algorithme par an.
    • Si vous inventez un algorithme, écrivez un papier, faites des conférences, devenez célèbres ! Il n'y a rien de négatif à cela, bien que cela risque d'être extrêmement rare.


    Un des plus grands problèmes est que les développeurs C++ ne connaissent pas leurs algorithmes : prenez du temps, apprenez-les, c'est vital ! Vous gagnerez du temps, des performances, de la lisibilité, de la sécurité.

    Apprenez ce qu'ils font, apprenez à les reconnaître, apprenez à jouer avec en réduisant itérativement la complexité de votre code.

    Le code généré sera également considérablement plus évolutif.


    Pas de primitives de synchronisation brutes

    Les primitives de synchronisation en question sont des mutex, des atomic, des sémaphores, des barrières.

    Vous avez un pourcentage de chance extrêmement élevé de vous tromper, générant des erreurs du genre le plus teigneux : les data race ponctuelles (une ou deux fois par semaine, votre application va crasher, amusez-vous à débuguer ).

    De plus, si vous voulez que vos performances augmentent le plus proportionnellement possible au nombre de cœurs, la synchronisation n'est pas votre alliée.

    Il faut penser en termes de tâches asynchrones. Le standard ne fournit malheureusement aucun outil pour ceci actuellement.

    S. Parent donne quelques clés pour disposer d'outils de base.


    Pas de pointeurs bruts

    Un pointeur brut peut être ici :
    • T* p = new T
    • std::unique_ptr<T>
    • std::shared_ptr<T>


    On utilise les pointeurs pour un nombre conséquent de raisons. Très peu se justifient, notamment dans les interfaces. On doit être capable de manipuler des Objets, sans passer par des pointeurs bruts.

    Pour les conteneurs, on dispose déjà de conteneurs non-intrusifs dans la STL, il n'est ainsi pas nécessaire d'hériter d'une classe Node pour être stocké dans un std::vector.

    Le problème se pose pour le polymorphisme dynamique où l'on commence à vouloir ajouter une classe de base pour la hiérarchie afin de pouvoir la stocker, alors qu'il est possible de le faire de façon non-intrusive, ainsi que Sean Parent va le montrer dans ce code :
    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
    class object_t {
      public:
        template<typename T> // T models Drawable
        object_t(T x) : self_(make_shared<model<T>>(move(x)))
        { }
        void draw(ostream& out, size_t position) const
        { self_->draw_(out, position); }
     
      private:
        struct concept_t {
            virtual ~concept_t() = default;
            virtual void draw() const = 0;
        };
     
        template <typename T>
        struct model : concept_t {
            model(T x): data_(move(x)) { }
            void draw(ostream& out, size_t position) const
            { data_.draw(out, position); }
     
            T data_;
        };
     
        shared_ptr<const concept_t> self_; // [Ndlr] une copie de shared_ptr<const> copie l'objet contenu
    };
     
    using document_t = vector<object_t>;
     
    void draw(const document_t& x, ostream& out, size_t position)
    {
        out << string(position, ' ') << "<document>" << endl;
        for (const auto& e : x) e.draw(out, position + 2);
        out << string(position, ' ') << "</document>" << endl;
    }
    Les shared_ptr ne valent pas mieux que des globales : il devient impossible de résonner de façon locale sur le code, deux morceaux de code indépendants travaillent sur la même portion de mémoire.

    Il faut garder la possibilité de raisonner localement : le code sera plus simple à analyser, plus facile à intégrer, plus généraliste, plus correct, plus efficace.

    Sean Parent donne plus d'informations sur cette approche dans sa deuxième conférence intitulée Inheritance is the base class of Evil, "L'héritage est la classe mère du Vice" (résumé à venir prochainement).


    Conférence précédente : Bjarne Stroustrup - L'Essence du C++
    Évènement : GoingNative 2013

    Et vous,
    Qu'en pensez-vous ?

  2. #2
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    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 292
    Par défaut
    À noter aussi l'exemple didactique d'un refactoring de code dans le sujet "pas de raw for". Si on prend une liste d'éléments contigus (des random access containers), deux questions de réorganisation des éléments :
    1- comment remonter (/descendre) un ensemble contigus d'éléments dans la liste ? -> avec std::rotate
    2- comment prendre un ensemble non contigus d'éléments, et les déplacer ailleurs et les rendre contigus ? -> avec std::stable_partition.

    D'où le "know your algorithms".
    C'est une des meilleures illustrations du conseil, "utiliser les algorithmes standards" que j'ai pu voir. Souvent, on se cantonne à des for-each, des find_if faits à la main (à cause du besoin de l'écriture lourde des foncteurs), au mieux on utilise des std::sort. Là, on voit une mise en oeuvre d'un algo pas si trivial, et d'une façon efficace qui aura des impacts bénéfiques sur les performances.
    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...

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut
    Citation Envoyé par germinolegrand Voir le message
    Pas de pointeurs bruts

    Un pointeur brut peut être ici :
    • T* p = new T
    • std::unique_ptr<T>
    • std::shared_ptr<T>
    J'ai personnellement du mal à voir comment ça peut être compatible si on a des objets à sémantique d'entité qui sont référencés par d'autres (type association UML) : il faut bien un lien entre la personne et ses magasines (on aura un truc comme un vector<Magazine*> ou vector<std::shared_ptr<Magazine>>). Je vois pas comment on peut s'en passer à moins de ne pas travailler avec des objets à sémantique d'entité (ce qui est peut être le cas de Sean Parent)

  4. #4
    Membre émérite

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par CedricMocquillon Voir le message
    "on aura un truc comme un vector<Magazine*> ou vector<std::shared_ptr<Magazine>>"
    Ou bien vector< magazine_id > avec map< int, Magazine >
    #edit Ou bien map< Magazine_id, Magazine >

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut
    @PilloBuenaGente je comprend pas bien ton édit, si on a deux classes comme l'exemple de Wikipedia: Person et Magazine et que l'on veut lister les magazines auxquels une personne est abonnée, soit on stocke dans Person les références aux magazines soit on passe comme tu l'indiquais par des id.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Person
    {
    public:
      void add(Magazine* m) { magazines_m.push_back(m); }
      std::vector<Magazine*> const& magazines() const { return magazines_m; }
    private:
      std::vector<Magazine*> magazines_m;
    };
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Person
    {
    public:
      typedef size_t magazine_id_t;
     
      void add(magazine_id_t m) { magazines_m.push_back(m); }
      std::vector<magazine_id_t> const& magazines() const { return magazines_m; }
    private:
      std::vector<magazine_id_t> magazines_m;
    };
    Par contre maintenant si je veux lister les titres des magazines auxquels une personne est abonnée, par ta méthode c'est bien plus lourd puisqu'il faut que je connaisse le manager (au sens informatique) des magazines. De plus on passe d'un accès en temps constant (O(1)) à un accès en temps logarithmique (la recherche dans la map) ce qui n'est vraiment pas efficace.

  6. #6
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par CedricMocquillon Voir le message
    J'ai personnellement du mal à voir comment ça peut être compatible si on a des objets à sémantique d'entité qui sont référencés par d'autres (type association UML) : il faut bien un lien entre la personne et ses magasines (on aura un truc comme un vector<Magazine*> ou vector<std::shared_ptr<Magazine>>). Je vois pas comment on peut s'en passer à moins de ne pas travailler avec des objets à sémantique d'entité (ce qui est peut être le cas de Sean Parent)
    Dans son cas, il avait des objets dont il aurait aimé que la sémantique soit une sémantique de valeur, mais pour lesquels il voulait un comportement polymorphe. Le fait de les gérer par pointeur et de dire "maintenant, ils ont une sémantique d'entité" le gênait.

    Sa solution s'approche un peu des value_ptr, clone_ptr ou autres (il la développe dans sa deuxième présentation), mais avec la différence qu'il n'impose pas de dériver d'une classe de base. J'avoue que je suis assez tenté de l'essayer à la prochaine occasion.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Citation Envoyé par CedricMocquillon Voir le message
    J'ai personnellement du mal à voir comment ça peut être compatible si on a des objets à sémantique d'entité qui sont référencés par d'autres (type association UML) : il faut bien un lien entre la personne et ses magasines (on aura un truc comme un vector<Magazine*> ou vector<std::shared_ptr<Magazine>>). Je vois pas comment on peut s'en passer à moins de ne pas travailler avec des objets à sémantique d'entité (ce qui est peut être le cas de Sean Parent)
    A vrai dire, dés que l'on parle d'entité, on parle d'objet identifiable "de manière unique et non ambigüe".

    Bien sûr, l'adresse d'un objet est une des manières qui permettent une telle identification, mais, de manière générale, il y a toujours certaines données qui représentent cette unicité référentielle :

    Que ce soit le numéro d'un compte bancaire, le numéro IBAN d'un livre, le numéro de sécu d'une personne ou le numéro de série d'autre chose, tu trouveras toujours une donnée qui te permettra de dire que c'est cet objet là en particulier qui t'intéresse et non celui qui se trouve juste à coté.

    Il n'y a strictement rien qui t'oblige à utiliser un (pointeur sur l') objet associé pour représenter l'association : tu peux parfaitement te contenter d'utiliser cet identifiant unique.

    C'est d'ailleurs généralement beaucoup plus efficace dans le sens où les associations sont souvent bidirectionnelles et de type "un à plusieurs" : chaque personne peut être abonnée à 0 ou plusieurs magazines, mais chaque magazine peut avoir 0 à plusieurs abonnés.

    En ne plaçant que l'identifiant unique du magazine (au niveau de la personne) ou de la personne (au niveau du magazine), voire, en créant une abstraction supplémentaire (qui peut être utilisé comme identifiant unique) qui représente à chaque fois la relation entre une personne bien particulière et un magazine bien particulier, tu te facilite énormément le travail de recherche.

    Note d'ailleurs que c'est l'une des règles à respecter au niveau des BDD pour pouvoir dire qu'elles sont normalisées (même si je ne sait plus le niveau de normalisation )
    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

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    301
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 301
    Par défaut
    Je commence à douter de l'approche que j'ai de cette problématique:
    Si on prend l'exemple Person / Magazine avec une association plusieurs à plusieurs, on a plusieurs approches possibles:
    Celle que j'utilise jusqu'à maintenant utilise des pointeurs, j'ai également un manager de personnes et de magazines qui est utilisé lors de la lecture des data pour mettre à jour les relations. Niveau code ça donne en gros ça:
    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
     
    class Person
    {
    public:
      typedef std::size_t id_type;
      typedef std::vector<std::shared_ptr<Magazine>> magazines_t;
     
      Person(id_type id) : id_m(id) {}
     
      id_type id() const { return id_m; }
     
      void add_magazine(std::shared_ptr<Magazine> const& m) { magazines_m.push_back(m); }
     
      magazines_t const& magazines() const { return magazines_m; }
    private:
      id_m;
      magazines_t magazines_m;
    };
    et la classe magazine
    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
     
    class Magazine
    {
    public:
      typedef std::size_t id_type;
      typedef std::vector<std::shared_ptr<Person>> persons_t;
     
      Magazine(id_type id, std::string title) : id_m(id), title_m(std::move(title) {}
     
      id_type id() const { return id_m; }
     
      std::string const& title() const { return title_m; }
     
      void add_person(std::shared_ptr<Person> const& p) { persons_m.push_back(p); }
     
      persons_t const& persons() const { return persons_m; }
    private:
      id_type id_m;
      std::string title_m;
      persons_t persons_m;
    };
    au niveau des managers, j'ai ça:
    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
     
    class MagazineManager
    {
      typedef Magazine::id_type magazine_id_t;
    public:
      void add_magazine(std::shared_ptr<Magazine> const& m) { magazines_m[m->id()] = m; }  //avec en plus une gestion des collisions de clef avec levée d'exception
     
      std::shared_ptr<Magazine> const& get_magazine(magazine_id_t const& id) { return magazines_m[id]; } //avec en plus gestion des magazines manquant avec levée d'exception
     
    private:
     
      std::map<magazine_id_t, std::shared_ptr<Magazine>> magazines_m;
    };
     
    class PersonManager
    {
      typedef Person::id_type person_id_t;
    public:
      void add_person(std::shared_ptr<Person> const& p) { persons_m[p->id()] = p; }  //avec en plus une gestion des collisions de clef avec levée d'exception
     
      std::shared_ptr<Person> const& get_magazine(person_id_t const& id) { return persons_m[id]; } //avec en plus gestion des magazines manquant avec levée d'exception
     
    private:
     
      std::map<person_id_t, std::shared_ptr<Person>> persons_m;
    };
    au niveau de la lecture des données, j'ai effectivement besoin que la base soit normalisée, j'ai donc trois tables: Person, Magazine, et Subscriptions. Je commence par peupler mes managers avec les tables person et magazine ensuite lors de la lecture des subscriptions, ça donne en gros ça:
    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
    void read_subscription(std::istream& in, PersonManager const& pm, MagazineManager const& mm)
    {
      //lectures des données de la base  
      Person::id_type id_p;
      Magazine::id_type id_m;
      in >> id_p >> id_m;
     
      //récupération des entités via les managers
      auto const& person = pm.get_person(id_p);
      auto const& magazine = mm.get_magazine(id_m);
     
      //mise à jour des relations entre les entités
      person.add_magazine(magazine);
      magazine.add_person(person);
    }
    Voila pour mon approche, maintenant, on peut effectivement passer par des identifiants uniques: au niveau de la classe Person, on aurait donc une liste d'identifiants de Magazine (donc une liste de Magazine::id_type) et non plus directement les références (au sens large du terme) directes aux objets. L'inconvénient que je vois à cette approche (mais bon j'ai pas trop de recul ;-) ) c'est que pour lister les magazines d'une personne, je vais avoir besoin en plus de la personne, du manager de magazines (sinon comment avoir les objets magazines). Pour moi, je vais passer de ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(auto const& m: p->magazines())
      std::cout << m->title() << '\n';
    à quelque chose comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(auto const& idm : p->magazines())
      std::cout << mm.get_magazine(idm)->title() << '\n';  //avec mm le MagazineManager
    La différence d'écriture n'est pas en soit très importante (en plus ça dépend fortement du choix de nommage) mais par contre je passe d'un accès en O(1)*le nombre de magazines de la personne à un accès en O(log n)*le nombre de magazines de la personne avec n le nombre de magazines dans la Bd!
    On pourrait toujours essayer de "limiter la casse" au niveau du manager (en utilisant par exemple des unordered_map) mais on aura toujours un overhead non négligeable.

  9. #9
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Attention quand même, dans la conférence Sean Parent utilise une définition assez spécial de pointeur brut. Pour lui un pointeur brut est "a pointer to an object with implied ownership and reference semantics". Par exemple pour lui, std::unique_ptr et std::shared_ptr sont des pointeurs bruts.

    Donc il ne met pas en cause les pointeurs d'association, en fait il n'en parle pas du tout.

  10. #10
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    @CedricMocquillon

    Si tes managers possèdent les magazines / personnes, pourquoi avoir des shared_ptr dans tes magazines / personnes ? Des weak_ptr auraient ici leurs utilités.

    Ça sens les références cycliques à plein nez, attention.

    edit: ou des unique_ptr dans tes managers, et des pointeurs nus dans magazines / personnes.

  11. #11
    Invité de passage
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2013
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Etats-Unis

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

    Informations forums :
    Inscription : Novembre 2013
    Messages : 1
    Par défaut
    Citation Envoyé par CedricMocquillon Voir le message
    J'ai personnellement du mal à voir comment ça peut être compatible si on a des objets à sémantique d'entité qui sont référencés par d'autres (type association UML) : il faut bien un lien entre la personne et ses magasines (on aura un truc comme un vector<Magazine*> ou vector<std::shared_ptr<Magazine>>). Je vois pas comment on peut s'en passer à moins de ne pas travailler avec des objets à sémantique d'entité (ce qui est peut être le cas de Sean Parent)
    Apologies for using English - my high school French is rusty. To be precise, what I said was that a "raw pointer" is a pointer with implied ownership. What you describe is a general relationship - which is a different use of a pointer. I wanted to clarify because that misunderstanding seems to have derailed this thread.

  12. #12
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    @seanparent: I'm really happy to see you here, and please feel free to speak english ; though I will have to translate your answers so that people here whose english is rusty () can clearly understand you . (if you need some translation from french to english, feel free to ask also )

    Citation Envoyé par seanparent
    Apologies for using English - my high school French is rusty. To be precise, what I said was that a "raw pointer" is a pointer with implied ownership. What you describe is a general relationship - which is a different use of a pointer. I wanted to clarify because that misunderstanding seems to have derailed this thread.
    Citation Envoyé par traduction
    Je m'excuse pour l'utilisation de l'anglais - mon français datant du lycée est un peu rouillé. Pour être précis, ce que j'ai dit est qu'un "pointeur brut" est un pointeur avec responsabilité implicite. Ce que vous décrivez est une relation de type générale - ce qui est un usage différent d'un pointeur. Je souhaitais le clarifier car il semble que cette incompréhension ait dérouté ce thread.

Discussions similaires

  1. Réponses: 7
    Dernier message: 20/02/2014, 13h36
  2. Réponses: 9
    Dernier message: 15/09/2013, 08h51
  3. Réponses: 3
    Dernier message: 08/09/2013, 18h55
  4. Conception d'une classe parente
    Par VincentB dans le forum Langage
    Réponses: 9
    Dernier message: 24/06/2003, 17h28
  5. DLL, affichage et parent...
    Par KRis dans le forum Composants VCL
    Réponses: 6
    Dernier message: 13/12/2002, 17h01

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