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

Normalisation C++ Discussion :

Instanciation d'un en-tête "shared_ptr.h" en c++ dans la norme avant la 11


Sujet :

Normalisation C++

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 62
    Points : 34
    Points
    34
    Par défaut Instanciation d'un en-tête "shared_ptr.h" en c++ dans la norme avant la 11
    Bonjour,

    Je souhaite connaître la manière d'instancier avant la norme 11 en c++ un en-tête shared_ptr.h (ci-dessous) dans un fichier .cpp de ce type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    shared_ptr<Personne> p = new Personne(nom)
    En effet, le shared_ptr ne peut être instancié avec le makeshared de la norme 11 du c++.

    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
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    #ifndef SHAREDPTR_H
    #define SHAREDPTR_H
    #include <assert.h>
    namespace ag {
    //--- classe d'exception
    class ref_error {};
     
    //--- modèle du pointeur partagé
    template <typename T>
    class shared_ptr
    {
    		public:
    //--- opérateurs de déréférencement
    		T* operator->() const throw()
    		{
    			assert(ptr_ref!=NULL);
    			return ptr_ref->get();
    		}
    		T& operator*() const throw()
    		{
    			assert(ptr_ref!=NULL);
    			return *(ptr_ref->get());
    		}
    //--- accès à la donnée interne
    		T* get() const throw(){
    			assert(ptr_ref!=NULL);
    			return ptr_ref->get();
    		}
    //--- constructeurs / destructeur
    		shared_ptr(T* p){ptr_ref=new shared_ptr_ref(p);}
    		shared_ptr() throw() :ptr_ref(0){}
    		shared_ptr(const shared_ptr& p) throw()
    		{
    			if(p.ptr_ref)
    				p.ptr_ref->Prend(); // prend la responsabilité de l'objet partagé
    			ptr_ref=p.ptr_ref;
    		}
    		~shared_ptr()
    		{
    			if(ptr_ref)
    				ptr_ref->Libere(); // perd la responsabilité de l'objet partagé
    		}
    //---affectation
    		shared_ptr& operator=(const shared_ptr& p)
    		{
    			if(ptr_ref)
    				ptr_ref->Libere(); // perd une responsabilité sur l'ancien objet
    			if(p.ptr_ref)
    				p.ptr_ref->Prend();// prend une responsabilité sur un nouvel objet
    			ptr_ref=p.ptr_ref;
    			return *this;
    		}
    		shared_ptr& operator=(T* ptr)
    		{
    			if(ptr_ref) ptr_ref->Libere();
    			ptr_ref = new shared_ptr_ref(ptr);
    			return *this;
    		}
     
     
    //--- comparaisons
    		bool operator==(T* ptr) const
    		{
    			bool ok=false;
    			if(ptr_ref==0)
    				ok =(ptr==0);
    			else
    				ok = (ptr_ref->get()==ptr);
    			return ok;
    		}
    		bool operator!=(T* ptr) const {return !operator==(ptr);}
    		operator bool() const
            {
                return (ptr_ref!=0 && ptr_ref->get()!=0);
            }
     
    		private:
    //--- classe assistante représentant l'objet partagé
    		class shared_ptr_ref
    		{
    				T* ptr; // la donnée interne
    				mutable int count; // le comptage de références : mutable car amené à changer même sur un shared_ptr_ref const.
    	// on interdit la copie et l'affectation
    				shared_ptr_ref(const shared_ptr_ref&);
    				void operator=(const shared_ptr_ref&);
     
    				public:
    	// constructeurs / destructeur
    				explicit shared_ptr_ref(T* p) throw() :ptr(p),count(1){}
    				~shared_ptr_ref(){delete ptr;}
    	// gestion des références
    				void Prend() const throw() {++count;}
    				void Libere(){--count; if(count==0) delete this;}
    	// accès à la donnée interne
    				T* get() const throw(){return ptr;}
    		};
    		mutable shared_ptr_ref* ptr_ref; // référence partagée
    };
     
     
    } // fin du namespace
    #endif
    Cette étude me permettra de comprendre de manière basique le fonctionnement des pointeurs intelligents.

    D'avance merci

  2. #2
    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 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    shared_ptr est arrivé en C++11 en même temps que make_shared.
    Ton shared_ptr là est juste une classe et tu peux litérallement lire les constructeurs et opérateurs d'affectation pour en instancier un objet.
    Donc le problème ou l'erreur est...?
    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.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 62
    Points : 34
    Points
    34
    Par défaut
    Merci Bousk,
    Si je comprend bien, je ne peux pas instancier un objet à l'aide de l'en-tête shared_ptr.h en l'ajoutant avec #include dans un fichier .cpp avant la norme 11 ?
    En effet, je ne souhaite pas forcément utiliser "make_shared" mais une allocation dynamique de type new ou autre.
    En fait, je souhaite avant la norme c++ 11, créer une allocation dynamique à l'aide de ce fichier en-tête. Est-ce possible et comment faire ?
    Merci d'avance

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Tu as donné la réponse dans ta question initiale, il faut utiliser l'opérateur new (mais jamais le delete) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    shared_ptr<Personne> p = new Personne(nom);

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 62
    Points : 34
    Points
    34
    Par défaut
    Merci dalfab,

    Dans cet exemple en c++ avant la norme 11, le compilateur (Visual Studio 2010) trouve de drôles d'erreurs que je ne saurais résoudre seul :

    personne.h
    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
    #ifndef PERSONNE_H
    #define PERSONNE_H
    #include <string>
     
    class Logement;
     
    class Personne
    {
        std::string identite;
        Logement *residence;
    public:
        Personne(std::string id);
        std::string ToString() const;
        void Emmenage(Logement *l);
     
    };
     
    #endif // PERSONNE_H
    personne.cpp
    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
    #include "personne.h"
    #include "logement.h"
    #include <sstream>
     
    Personne::Personne(std::string id):identite(id),residence(nullptr)
    {
    }
     
    void Personne::Emmenage(Logement *l)
    {
        if(residence!=nullptr)
            residence->Depart(this);
        residence = l;
        if(residence!=nullptr)
            residence->Arrivee(this);
    }
     
    std::string Personne::ToString() const
    {
       std::ostringstream flux;
       flux << identite;
       if(residence!=nullptr)
       {
           flux << " ("<<residence->ToString()<<")";
       }
       return flux.str();
    }
    logement.h
    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
    #ifndef LOGEMENT_H
    #define LOGEMENT_H
    #include <string>
    #include <set>
     
    class Personne;
     
    class Logement
    {
        std::string adresse;
        std::set<Personne*> occupants;
    public:
        Logement(std::string ad);
        std::string ToString() const;
        void Arrivee(Personne* p);
        void Depart(Personne *p);
        std::string ListeOccupants() const;
    };
     
    #endif // LOGEMENT_H
    logement.cpp
    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
    #include "logement.h"
    #include "personne.h"
    #include <sstream>
     
    Logement::Logement(std::string ad):adresse(ad)
    {
    }
     
    std::string Logement::ToString() const
    {
        return adresse;
    }
     
    void Logement::Arrivee(Personne *p)
    {
        occupants.insert(p);
    }
     
    void Logement::Depart(Personne *p)
    {
        occupants.erase(p);
    }
     
    std::string Logement::ListeOccupants() const
    {
        std::ostringstream flux;
    	/*std::set<Personne*> Logement::occupants;*/
        for(std::set<Personne*>::iterator i=occupants.begin();i!=occupants.end();++i)
        {
            flux << (*i)->ToString() << ',';
        }
        return flux.str();
    }
    shared_ptr.h
    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
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    #ifndef SHAREDPTR_H
    #define SHAREDPTR_H
    #include <assert.h>
    namespace ag {
    //--- classe d'exception
    class ref_error {};
     
    //--- modèle du pointeur partagé
    template <typename T>
    class shared_ptr
    {
    		public:
    //--- opérateurs de déréférencement
    		T* operator->() const throw()
    		{
    			assert(ptr_ref!=NULL);
    			return ptr_ref->get();
    		}
    		T& operator*() const throw()
    		{
    			assert(ptr_ref!=NULL);
    			return *(ptr_ref->get());
    		}
    //--- accès à la donnée interne
    		T* get() const throw(){
    			assert(ptr_ref!=NULL);
    			return ptr_ref->get();
    		}
    //--- constructeurs / destructeur
    		shared_ptr(T* p){ptr_ref=new shared_ptr_ref(p);}
    		shared_ptr() throw() :ptr_ref(0){}
    		shared_ptr(const shared_ptr& p) throw()
    		{
    			if(p.ptr_ref)
    				p.ptr_ref->Prend(); // prend la responsabilité de l'objet partagé
    			ptr_ref=p.ptr_ref;
    		}
    		~shared_ptr()
    		{
    			if(ptr_ref)
    				ptr_ref->Libere(); // perd la responsabilité de l'objet partagé
    		}
    //---affectation
    		shared_ptr& operator=(const shared_ptr& p)
    		{
    			if(ptr_ref)
    				ptr_ref->Libere(); // perd une responsabilité sur l'ancien objet
    			if(p.ptr_ref)
    				p.ptr_ref->Prend();// prend une responsabilité sur un nouvel objet
    			ptr_ref=p.ptr_ref;
    			return *this;
    		}
    		shared_ptr& operator=(T* ptr)
    		{
    			if(ptr_ref) ptr_ref->Libere();
    			ptr_ref = new shared_ptr_ref(ptr);
    			return *this;
    		}
     
     
    //--- comparaisons
    		bool operator==(T* ptr) const
    		{
    			bool ok=false;
    			if(ptr_ref==0)
    				ok =(ptr==0);
    			else
    				ok = (ptr_ref->get()==ptr);
    			return ok;
    		}
    		bool operator!=(T* ptr) const {return !operator==(ptr);}
    		operator bool() const
            {
                return (ptr_ref!=0 && ptr_ref->get()!=0);
            }
     
    		private:
    //--- classe assistante représentant l'objet partagé
    		class shared_ptr_ref
    		{
    				T* ptr; // la donnée interne
    				mutable int count; // le comptage de références : mutable car amené à changer même sur un shared_ptr_ref const.
    	// on interdit la copie et l'affectation
    				shared_ptr_ref(const shared_ptr_ref&);
    				void operator=(const shared_ptr_ref&);
     
    				public:
    	// constructeurs / destructeur
    				explicit shared_ptr_ref(T* p) throw() :ptr(p),count(1){}
    				~shared_ptr_ref(){delete ptr;}
    	// gestion des références
    				void Prend() const throw() {++count;}
    				void Libere(){--count; if(count==0) delete this;}
    	// accès à la donnée interne
    				T* get() const throw(){return ptr;}
    		};
    		mutable shared_ptr_ref* ptr_ref; // référence partagée
    };
     
     
    } // fin du namespace
    #endif
    ville.h
    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
    #ifndef VILLE_H
    #define VILLE_H
    #include <set>
    #include <string>
    #include "shared_ptr.h"
     
    class Logement;
     
    class Ville
    {
        std::set<ag::shared_ptr<Logement> > logements;
     
    public:
        Ville();
        std::string ListeLogements() const;
        Logement* CreeLogement(std::string adresse);
    };
     
    #endif // VILLE_H
    ville.cpp
    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
    #include "ville.h"
    #include "logement.h"
    #include "shared_ptr.h"
    #include <sstream>
    #include <algorithm>
     
    Ville::Ville()
    {
    }
     
    std::string Ville::ListeLogements() const
    {
        std::ostringstream flux;
     
        for(std::set<ag::shared_ptr<Logement>>::iterator i=logements.begin();i!=logements.end();++i)
        {
             flux << (*i)->ToString() << ',';
        }
        return flux.str();
     
    }
     
    Logement* Ville::CreeLogement(std::string adresse)
    {
        ag::shared_ptr<Logement> l = new Logement(adresse);
        logements.insert(l);
    	return l.get();
    }
    main.cpp
    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
    #include <iostream>
    #include "ville.h"
    #include "personne.h"
    #include "logement.h"
     
    using namespace std;
     
    int main()
    {
    	char z;
        cout << "Bienvenue dans ma ville !" << endl;
        Ville city;
        Logement *l1 = city.CreeLogement("15, rue des fleurs");
        Personne p1("paul"),p2("john"),p3("georges"),p4("ringo");
     
        p1.Emmenage(l1);
        p2.Emmenage(l1);
        p3.Emmenage(l1);
        p4.Emmenage(l1);
     
        cout << "Occupants de l1 (normalment 4)"<<endl;
        cout << l1->ListeOccupants() << endl;
     
        Logement *l2 = city.CreeLogement("23 rue des roses");
        p2.Emmenage(l2);
        cout << "Affichage d'une personne :"<<p2.ToString() << endl;
        cout << "Occupants de l1 (3) :"<<l1->ListeOccupants() << endl;
        cout << "Occupants de l2 (1) :"<<l2->ListeOccupants() << endl;
     
        cout << "Liste des logements : ";
        cout << city.ListeLogements()<<endl;
    	cin >> z;
        return 0;
    }
    D'avance merci de votre aide.

  6. #6
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Difficile de répondre sans question précise. Ça ne compile pas? Que dit le compilateur? Ça ne linke pas? Que dit le linkeur? Ça ne fait pas ce qui est attendu? Qu'attend-t-on ? Ça plante ? En faisant quoi et à quel moment ?

    Le ag::shared_ptr<> ne peut pas être mis dans un std::set<> car il n'est pas comparable, ça risque de ne pas compiler ou de donner des résultats bizarres. Il faudrait fournir un foncteur de comparaison à std::set<> ou bien ajouter la possibilité de comparer des ag::shared_ptr<>.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template<class T>
    bool operator<( ag::shared_ptr<T> const& g, ag::shared_ptr<T> const& d ) {
        return g.get() < d.get();
    }

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    62
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 62
    Points : 34
    Points
    34
    Par défaut
    Merci infiniment dalfab,
    Bravo, ça fonctionne maintenant !

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

Discussions similaires

  1. Quote et double quote
    Par aktos dans le forum Langage
    Réponses: 8
    Dernier message: 05/01/2007, 19h55

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