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 :

classe qui ne s'instancie que comme pointeur??


Sujet :

C++

  1. #1
    Membre régulier Avatar de yashiro
    Inscrit en
    Mars 2004
    Messages
    214
    Détails du profil
    Informations forums :
    Inscription : Mars 2004
    Messages : 214
    Points : 82
    Points
    82
    Par défaut classe qui ne s'instancie que comme pointeur??
    Comment procède-t-on pour créer des classe qui ne peuvent être instanciée que sous forme de pointeur?

    J'ai essayé de rendre privé tous ses constructeurs et surcharger l'opérateur "new", ça m'a permi de restreindre la déclaration de cette classe à un pointeur mais lorsque j'appèle le "new" k'ai des erreur d'accès
    voici ce que j'ai pu faire:

    L'interface de la classe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    nonpublic.h
     
    // Une classe qui n'a pas de constructeur public
    #include<stddef.h>
     
    class nonpublic
     { nonpublic(int = 0);
       int x;
       public:
        void Print();
        void* operator new(size_t);
     };
    La définition de la classe

    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
    nonpublic.cpp
     
    #include<stdlib.h>
    #include<iostream>
    #include<stddef.h>
    #include"nonpublic.h"
     
    nonpublic::nonpublic(int i): x(i) {} 
     
    void nonpublic::Print() { std::cout<<x<<std::endl; }
     
    void* nonpublic::operator new(size_t size) 
     { 
       char* chn = ::new char[size];
       void* var=static_cast<void*>(chn);
       nonpublic* val= static_cast<nonpublic* >(var); 
       return val;
     }
    Mais lorsque je met cette instruction dans le main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nonpublic* n = new nonpublic;
    le compilo me renvoie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    C:\Dev-Cpp\Projet\nonpublic\nonpublic.h `nonpublic::nonpublic(int = 0)' is private
    passionné de développement

  2. #2
    Membre émérite
    Avatar de la drogue c'est mal
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    2 253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 2 253
    Points : 2 747
    Points
    2 747
    Par défaut
    tu crées une classe factory.
    tu mets en private le contructeur de ta classe avec le factory en friend
    tu crées une methode "GetInstanceMaClass" dans ta factory.
    il y a du linge sur la corde à linge

  3. #3
    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 peut en plus planquer le destructeur et renvoyer des handle-intelligents (comme les pointeurs) amis qui seront les seuls à même de détruire les objets.
    La factory renvoie des handles, les handles en fin de portée (extensible avec telle ou telle autre sémantique de copie) s'occupent de libérer.



    Mais ... pourquoi faire une telle chose ?
    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...

  4. #4
    Membre éclairé
    Avatar de Edouard Kaiser
    Profil pro
    Inscrit en
    Février 2004
    Messages
    521
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2004
    Messages : 521
    Points : 756
    Points
    756
    Par défaut
    Peut être qu'il souhaite implémenter le design pattern factory.

  5. #5
    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
    Je ne trouve pas qu'il soit besoin de s'interdire les objets automatiques pour autant. Interdire les copie sur les objets qui sont sensés avoir une sémantique d'entité suffit amplement je trouve. On voit vite que ce sont des pointeurs qui sont attendus en sortie de la factory.
    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...

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Un cas ou interdire l'allocation des objets sur la pile est intéressant, c'est lorsque l'on souhaite qu'ils possèdent un comportement "suicidaire", c-à-d que l'objet à un moment de sa vie effectue lui même un delete this.
    Dans ce cas, il est inutile de déclarer tous les constructeurs comme fonctions membre privées, déclarer le destructeur en partie privée suffit.

    Sinon, la solution brutale pour forcer l'allocation sur le tas, c'est comme indiqué : mettre tous les constructeurs en partie privée et fournir une fonction de type usine.

  7. #7
    Rédacteur

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

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Si une classe fait un delete this, je me poserai des questions sur le gars qui l'a programmée.

  8. #8
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Si quelqu'un se pose des question sur moi parce que je fais delete this, je me poserai des questions sur lui
    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.

  9. #9
    Rédacteur

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

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    On ne sait jamais
    Plus sérieusement, à part si on sait exactement ce qu'on fait - ce qui a l'air d'être ton cas -, vaut mieux de pas le faire - il y a tellement de possibilités qui pourraient aml se passer -

  10. #10
    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
    Il y a des frameworks qui obligent pratiquement à faire cela. Au début c'est dérangeant, après on comprend pourquoi et on s'y fait.
    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...

  11. #11
    Membre émérite
    Avatar de la drogue c'est mal
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    2 253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 2 253
    Points : 2 747
    Points
    2 747
    Par défaut
    Citation Envoyé par JolyLoic
    Si quelqu'un se pose des question sur moi parce que je fais delete this, je me poserai des questions sur lui
    les MFC le font
    il y a du linge sur la corde à linge

  12. #12
    Rédacteur

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

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Luc Hermitte
    Il y a des frameworks qui obligent pratiquement à faire cela. Au début c'est dérangeant, après on comprend pourquoi et on s'y fait.
    Ah ?
    C'est pourquoi alors les raisons ? - c'est vraiment pour me renseigner, hein -

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par Miles
    Si une classe fait un delete this, je me poserai des questions sur le gars qui l'a programmée.
    C'est pourtant un classique. Je ne suis pas un exemple, mais j'ai 7 ans de métier et je l'utilise parfois. Des API entières sont construites en se basant sur ce modèle, conçues par des gens dont j'estime la compétence bien au dela de la mienne.

    Si je me rappelle bien, il me semble que dans COM/DCOM les objets sont construits via une usine propre et incluent un comptage de référence, les clients ne peuvent ni construire ni détruire directement un objet. Lorsqu'ils n'utilisent plus une instance, ils la libère via une fonction membre. Cette instance detecte si elle est encore utilisée, et ce n'est pas le cas, elle se suicide.

    Un autre exemple, minimaliste et discutable. Tu fais du client/serveur. Quand un client se connecte, une tâche (thread) est crée pour satisfaire sa demande. Cette tâche est implantée par une instance d'une classe TâcheClient.
    La destruction de cette instance doit être effectuée lorsque la requête du client est satisfaite. Le suicide permet de créer cette sous tâche et de la laisser vivre sa vie, sans s'en occuper. Cela évite un système de communication compliqué où cette sous tâche devrait avertir un tiers que le travail est terminé afin qu'il la détruise.

  14. #14
    Rédacteur

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

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    D'accord, je vois pourquoi c'est utilisé. Effectivement, dans ce cas, ça passe Certains l'utilisent malheureusement pour faire des copies ou des bestioles du genre, et là ça peut faire très mal.

  15. #15
    Membre du Club
    Inscrit en
    Septembre 2003
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 49
    Points : 43
    Points
    43
    Par défaut
    soit une finction:

    void f()
    {

    T1 t1 = new T1; //1
    T2 t2 = new T2; //2

    }

    le standard dit que si dans 2 une exception est emise le compilateur doit detruire l'objet t1 (delete t1).

    donc si ~T1() est prive le compilateur ne peut pas proceder a la destruction de l'objet t1 et je connais certain compilteur qui refuserait de compiler un tel code
    a+

  16. #16
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Le compilateur doit détruire les objets en sortie de bloc ou lors d'un départ en exception donc dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void f()
    {
      T1 t1;
      T2 t2;
    }
    ~T1() et ~T2() sont appelés respectivement sur t1 et t2. Ce qui fait que si ces fonctions
    sont privées, ce code ne compile pas. Ca tombe bien, justement on voulait interdire l'allocation d'objet sur la pile.

    Maintenant si les objets sont alloué sur le tas,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void f()
    {
      T1 * t1 = new T1();
      T2 * t2 = new T2();
    }
    t1 et t2 sont des pointeurs et comme tout type scalaire, le compilateur n'appelera aucun destructeur.

    @adel_dz
    Je vois mal ce quelle position ton post défend. En tout cas, l'exemple fourni ne compilera sur aucun compilo connu

  17. #17
    Membre du Club
    Inscrit en
    Septembre 2003
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Septembre 2003
    Messages : 49
    Points : 43
    Points
    43
    Par défaut
    Ce que j'essais d'expliquer c'est qu'un destructeur prive c'est "evil"

    dans le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void f() 
    { 
      T1 * t1 = new T1(); 
      T2 * t2 = new T2(); 
    }

    si le constructeur T2() emet une exception le compileteur doit inserer du code pour detruire t1 (le standard le stipule) et si le destructeur de T1 est prive le compilateur DOIT s'en plaindre.
    a+

  18. #18
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Citation Envoyé par adel_dz
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void f() 
    { 
      T1 * t1 = new T1(); 
      T2 * t2 = new T2(); 
    }

    si le constructeur T2() emet une exception le compileteur doit inserer du code pour detruire t1 (le standard le stipule)
    Non.

    Si tu remplace T1* par un pointeur intelligent, alors ok, mais ce pointeur intelligent a alors toutes les chances :
    - D'être ami de T1
    ou
    - D'appeler une fonction de destruction de T1, et non pas son destructeur.
    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.

  19. #19
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par adel_dz
    Ce que j'essais d'expliquer c'est qu'un destructeur prive c'est "evil"
    C'est faux, et tu continues à confondre objet et pointeur. Il te suffirait d'écrire un exemple pour t'en rendre compte. Lorsque tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void f()
    {
      int i =10;
      throw runtime_error("error");
    }
    Le compilateur génère-t'il un code spécifique pour la destruction de i ?
    Il en va de même si i est un pointeur, car un pointeur même s'il pointe sur un objet reste un type scalaire.

    Ensuite, le coup du destructeur privé ce n'est pas une bidouille de programmeur, mais bel et bien une technique connue et éprouvée pour forcer l'allocation des instances d'une classe sur le tas. Cette technique est présentée entre autre dans "More Effective C++" de Scott Meyer chez Addison-Wesley (item 26) qui AMA fait référence en terme d'ouvrage de programmation.

    Merci à l'avenir de tester ce que tu avances avant de te répéter.

  20. #20
    Rédacteur

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

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

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Tout à fait d'accord, d'ailleurs Meyers n'est pas le seul partisan de cette manière de faire. Certains préconisent même destructeur (public et virtuel) ou privé.

Discussions similaires

  1. Réponses: 6
    Dernier message: 17/07/2008, 18h10
  2. Methode pour recuperer la classe qui instancie une JFrame
    Par ceres02 dans le forum Agents de placement/Fenêtres
    Réponses: 4
    Dernier message: 07/08/2007, 15h47
  3. Réponses: 6
    Dernier message: 06/04/2007, 21h20
  4. Réponses: 14
    Dernier message: 14/03/2005, 09h16
  5. Réponses: 8
    Dernier message: 04/08/2004, 14h17

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