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 :

Détection du mode de construction d'un objet


Sujet :

C++

  1. #1
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut Détection du mode de construction d'un objet
    Bonjour,

    Je cherche à savoir s'il est possible de connaitre le mode de construction d'un objet CObjet, à savoir : construit par new ou non construit par new.

    J'ai une classe CConteneur qui possède un pointeur sur cet objet et je voudrais savoir, lors de la destruction de la classe CConteneur, s'il faut appeler le delete CCobjet ou pas.

    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
     
    class CObjet
    {
    public:
       CObjet(void);
       ~CObjet(void);
       bool est_construit_par_new(void) const;
    };
     
    class CObjet2 : public CObjet
    {
    };
     
    class CConteneur
    {
    public:
       CConteneur(CObjet *Objet)
       : m_objet(Objet)
       {
       }
     
       ~CConteneur(void)
       {
          if(m_objet->est_construit_par_new() == true)
             delete m_objet;
       }
     
    private:
       CObjet *m_objet;
    };
    Il y a bien l'idée de définir l'opérateur new pour la classe CObjet, cela règle ce problème mais cela ne le règle pas en cas d'héritage (cas où la classe CConteneur reçoit un pointeur sur CObjet2) ou alors, il faut redéfinir l'opérateur new de toute la hiérarchie.

    Est ce que quelqu'un aurait une autre idée intelligente ?
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je ne connais aucun moyen de faire ça, sinon forcer la construction d'une façon où d'une autre (constructeur privé/protected et fonction statique Create).
    Mais à ce moment, il faut qu'il en soit de même pour les classes héritées...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

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

  3. #3
    Membre habitué
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    142
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 142
    Points : 154
    Points
    154
    Par défaut
    Salut,

    Peut être que tu pourra trouver un solution avec une surcharge de l'opérateur new.

  4. #4
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Tu ne penses pas que ton conteneur fait un peu trop de choses ?

    Cela dit, pour régler ce problème je mettrai un paramètre lors de l'ajout d'objets dans le conteneur, pour dire si le conteneur doit détruire l'objet ou pas.

    À priori, au moment où tu l'ajoutes, tu sais qui doit s'occuper de gérer la durée de vie.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par FunK92 Voir le message
    Peut être que tu pourra trouver un solution avec une surcharge de l'opérateur new.
    Ben justement, je voulais éviter de surcharger l'opérateur new car cela m'oblige à le surcharger dans toute la hiérarchie
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    A mon avis, il y a un problème de conception au niveau de la responsabilité de ton objet.
    Sinon, comme white_tentacle, soit tu rajoutes un booléen à ton conteneur pour dire s'il doit ou non détruire l'objet, soit tu rajoutes un booléen (type auto_delete) à ton objet et une méthode Destroy qui fait ou non le delete this.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 680
    Points : 858
    Points
    858
    Par défaut
    +1
    La destruction de l'objet n'est pas la responsabilité du conteneur.
    • Une classe ne doit avoir qu'une seule responsabilité.
    • La responsabilité de la destruction d'un objet revient à l'entité (classe, fonction) qui a créé l'objet.


    Si tu es confronté à une telle problématique, il y a de grandes chances que l'utilisation de pointeurs intelligents soit la meilleure solution.
    Cours : Initiation à CMake
    Projet : Scalpel, bibliothèque d'analyse de code source C++ (développement en cours)
    Ce message a été tapé avec un clavier en disposition bépo.

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

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    La manière dont l'objet a été alloué ne devrait en rien changer sa construction.
    La construction ce n'est rien de plus qu'un appel de fonction qui va initialiser une zone mémoire déjà allouée.
    Boost ftw

  9. #9
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    Bonjour,
    Il y a bien l'idée de définir l'opérateur new pour la classe CObjet, cela règle ce problème mais cela ne le règle pas en cas d'héritage (cas où la classe CConteneur reçoit un pointeur sur CObjet2) ou alors, il faut redéfinir l'opérateur new de toute la hiérarchie.
    Je comprends pas trop... si tu définie new pour CObject, et que CObject2 dérive de CObject... alors un "new CObject2" va bien appeler l'opérateur new de CObject ! (heureusement d'ailleurs).

    Maintenant, comme les autres, je ne sais pas pourquoi tu as besoin de connaitre le mode d'allocation... C'est même éminemment dangereux, quid d'un sous-type qui implémenterait ses propres new/delete ?
    Peut être en nous disant ce que tu cherches à obtenir (au final) on pourrait être d'une plus grande utilité ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  10. #10
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par nicroman Voir le message
    Je comprends pas trop... si tu définie new pour CObject, et que CObject2 dérive de CObject... alors un "new CObject2" va bien appeler l'opérateur new de CObject ! (heureusement d'ailleurs).
    C'est sûr cela ?

    Il me semblait que les fonctions new des classes était (implicitement ?) statiques. Donc dans ce cas, le CObjet::new() retourne un CObjet, le CObjet2::new() retourne un CObjet2 sans appeler CObjet::new().

    Tu ne ferais pas une petite confusion avec les constructeurs (qui eux vont bien être appelés en série) ?

    Citation Envoyé par white_tentacle Voir le message
    Tu ne penses pas que ton conteneur fait un peu trop de choses ?
    Je crois effectivement que je voulais faire faire un peu trop de choses à mon conteneur
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    C'est sûr cela ?

    Il me semblait que les fonctions new des classes était (implicitement ?) statiques. Donc dans ce cas, le CObjet::new() retourne un CObjet, le CObjet2::new() retourne un CObjet2 sans appeler CObjet::new().

    Tu ne ferais pas une petite confusion avec les constructeurs (qui eux vont bien être appelés en série) ?
    Il semblerait que ce soit un peu plus subtile :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    #include <cstdio>
    #include <cstdlib>
     
    void* operator new(size_t sz) {
       printf("global new\n");
       return malloc(sz);
    }
     
    void operator delete(void* m) {
      printf("global delete\n");
      free(m);
    }
     
     
    class A
    {
    public:
       void*operator new(size_t sz)
       {
          printf("A::new\n");
          return ::new char[sz];
       }
       void operator delete(void*p)
       {
          printf("A::delete\n");
          ::delete(p);
       }
    };
     
    class B :public A
    {
    public:
    };
     
    class C :public A
    {
    public:
       void*operator new(size_t sz)
       {
          printf("C::new\n");
          return ::new char[sz];
       }
       void operator delete(void*p)
       {
          printf("C::delete\n");
          ::delete(p);
       }
    };
     
    class D
    {
    public:
    };
     
    class E :public D
    {
    public:
       void*operator new(size_t sz)
       {
          printf("E::new\n");
          return new char[sz];// interdit
       }
       void operator delete(void*p)
       {
          printf("E::delete\n");
          delete(p);//interdit
       }
    };
    int main()
    {
       printf("A\n");
       delete new A();
       printf("B\n");
       delete new B();
       printf("C\n");
       delete new C();
       printf("D\n");
       delete new D();
       printf("E\n");
       delete new E();
     
    	return getchar();
    }
    Donne :
    A
    A::new
    global new
    A::delete
    global delete
    B
    A::new
    global new
    A::delete
    global delete
    C
    C::new
    global new
    C::delete
    global delete
    D
    global new
    global delete
    E
    E::new
    global new
    E::delete
    global delete
    A noter que gcc me donne :
    Citation Envoyé par gcc
    warning: deleting `void*' is undefined
    sur les lignes ::delete(p); des surcharges.

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    À mon avis, pour corriger le warning, il faudrait faire ceci à la place:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    delete[] static_cast<char*>(p);
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

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

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

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Il faut faire ::operator delete(p)
    Et il faut allouer avec ::operator new, pas new char[N]...

    Sinon ça invoque des comportements indéfinis dans tous les sens.
    Boost ftw

  14. #14
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Il semblerait que ce soit un peu plus subtile :
    Je suis désolé... je vois pas la subtilité....
    Tout se déroule comme un appel à un fonction "new" qui peut être surchargée ou non... avec une fonction globale ou non...
    A moins que j'ai raté une subtilité effectivement

    A: A surcharge new/delete, c'est ceux là qui sont appelé.
    B: B ne surcharge pas new/delete, mais hérite de A => c'est ceux de A qui sont appelé (d'ou mon intervention)
    C: C surcharge new/delete, c'est ceux là qui sont appelés
    D: D ne surcharge pas new/delete, et n'hérite de personne => les fonctions globales
    E: E surcharge new/delete, c'est ceux là qui sont appelés.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  15. #15
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Il faut faire ::operator delete(p)
    Et il faut allouer avec ::operator new, pas new char[N]...

    Sinon ça invoque des comportements indéfinis dans tous les sens.
    Tu peux préciser stp ?

    Notamment, il y aurait une différence entre ::operator new et ::new ?

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

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    operator new ça alloue de la mémoire, new ça appelle operator new puis ça construit.

    Construire deux objets au même emplacement mémoire c'est tout simplement interdit.
    Boost ftw

  17. #17
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Effectivement, j'ai écrit trop rapidement hier soir. dsl

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Construction d'un objet à partir résultat d'une requêtte
    Par amine1980 dans le forum Hibernate
    Réponses: 3
    Dernier message: 11/12/2008, 17h32
  2. détection de clic de souris sur un objet pixmap
    Par bouchecousue dans le forum Qt
    Réponses: 16
    Dernier message: 15/05/2008, 13h09
  3. Construction d'un Objet
    Par julien1451 dans le forum C++
    Réponses: 1
    Dernier message: 18/10/2007, 23h03
  4. Réponses: 4
    Dernier message: 16/02/2006, 17h45
  5. Réponses: 5
    Dernier message: 11/06/2004, 18h02

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