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 :

allouer un pointeur membre d'une classe mère dans une classe dérivée


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 65
    Points : 58
    Points
    58
    Par défaut allouer un pointeur membre d'une classe mère dans une classe dérivée
    bonjour à tous,

    je possède une classe mère X() dans laquelle je définis un pointeur en donnée privée. Maintenant, je souhaiterais, si possible, pouvoir allouer dynamique ce pointeur dans une classe dérivée, mais je ne vois pas comment faire avec la donnée qui est privée.

    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
     
    class X
    {
      private:
        double* m_pN;
     
      public:
        X();
        X(const X&);
        ~X();
        double* r_pN() const{return m_pN;};
     
    };
     
    class Xd : public X
    {
      public:
        Xd();
        ~Xd();
        int test();
     
    }
    voilà, j'aimerais qu'à l'appel de test, cela réalise l'allocation du pointeur de la classe mère. Je pense qu'en changeant la donnée privée en donnée protégée, cela doit fonctionner. Mais cela est-il possible en gardant la donnée privée ?

    est-ce qu'une solution du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    int Xd::test()
    {
      this->r_pN() = new double;
      return 1;
    }
    ça fonctionnerait ?

    Je vous remercie pour vos réponses.
    Cordialement.

  2. #2
    Candidat au Club
    Profil pro
    Inscrit en
    Novembre 2009
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Novembre 2009
    Messages : 1
    Points : 2
    Points
    2
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    this->r_pN() = new double;
    ne fonctionne pas car la méthode ne renvoie pas une LValue, il faut que tu retournes une référence pour faire ce style d'affectation.

    Pour que ta propriété reste privée dans la classe mère tu peux rendre ta classe fille friend de la classe mère, ou mettre un setteur dans la classe mère pour mettre à jour ta propriété privée.

    Cordialement

  3. #3
    Membre averti
    Homme Profil pro
    Analyse système
    Inscrit en
    Novembre 2008
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Novembre 2008
    Messages : 227
    Points : 311
    Points
    311
    Par défaut
    Une autre solution serait de déclaré "protected" le pointeur dans ta classe mère. Ainsi, la classe fille y a accès directement.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Il est toujours particulièrement délicat de tenter de déléguer un comportement dont on peut s'attendre à ce qu'il soit pris en charge par la classe mere à la classe dérivée.

    Ne serait-ce que parce que cela risque de nous faire contrevenir au fondement même de la POO : le RAII (Ressource Acquisition Is Initialization).

    C'est particulièrement le cas pour ce qui est de la gestion dynamique de la mémoire.

    En effet, même si ta classe de base est une classe abstraite, la délégation de l'allocation dynamique de la mémoire présentera le gros risque... d'oublier de l'effectuer dans une des classes dérivées, sans même compter sur les problèmes qui pourraient se poser lorsqu'il sera question de décider du responsable de la libération de la mémoire.

    Le principal corrollaire est que tu *risque* de te retrouver avec une instance de classe dérivée dans laquelle le pointeur ne serait pas initialisé, ou ne pointerait pas vers une adresse valide (allouée dynamiquement).

    Je te laisse imaginer le m...dier sans nom dans lequel tu te trouvera dans de telles circonstances

    La meilleure solution est donc de veiller à ce que la mémoire vers laquelle le pointeur pointe soit... allouée directement par la classe de base, au besoin, en transmettant le nombre d'éléments à allouer en paramètres:

    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 Base
    {
        public:
            Base(int size): ptr_double(new double[size]), size(size)
            {
            }
            virtual ~Base(){delete [] ptr_double;}
            /* ...*/
            int count() const{return size;}
            double operator[](int index) const
            {
                assert(index<size);
                return ptr_double[index];
            }
        private:
            int size;
            double * ptr_double;
    };
    class DeriveeUn : public Base
    {
        public:
            Derivee(): Base(3){}
            /* ... */
    };
    class DeriveeDeux : public Base
    {
        public:
            Derivee(): Base(6){}
            /* ... */
    };
    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
    int main()
    {
        Base * b = new Base(5);
        Base * d1  = new DeriveeUn;
        Base * d2 = new DeriveeDeux;
        std::cout<<b->count()<<std::endl; // affiche "5"
        std::cout<<d1->count()<<std::endl; // affiche "3"
        std::cout<<d2->count()<<std::endl; // affiche "6"
        double myDouble = (*b)[3] // ok
        double myDoubleError = (b*)[6]; // NOK asser(6<5)
        double otherDouble = (*d1)[2]; // ok
        double otherDoubleError = (*d1)[3]; // NOK asser(3<3)
        double lastDouble = (*d2)[5]; // ok
        double otherDoubleError = (*d1)[7]; // NOK asser(7<6)
        delete b;
        delete d1;
        delete d2;
        return 0;  
    }

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

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 264
    Points : 6 683
    Points
    6 683
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par koala01 Voir le message
    La meilleure solution est donc de veiller à ce que la mémoire vers laquelle le pointeur pointe soit... allouée directement par la classe de base, au besoin, en transmettant le nombre d'éléments à allouer en paramètres
    Ou mieux, d'utiliser un vecteur en protected:
    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
    #include <iostream>
    #include <vector>
    #include <algorithm>
     
    using namespace std;
     
    class Mere
    {
    public:
    	inline const vector<double> & r_pN() const { return m_pN; }
     
    protected:
    	vector<double> m_pN;
     
    };
     
    class Fille : public Mere
    {
    public:
    	Fille()
    	{
    		// remplissage du vecteur, par ex:
    		for ( size_t i = 0; i < 10; ++i )
    			m_pN.push_back( (float) i * 1.2 );
    	}
    };
     
    int main()
    {
    	Fille f;
    	copy( f.r_pN().begin(), f.r_pN().end(), ostream_iterator<float>(std::cout, " ") );
     
    	cin.get();
    	return 0;
    }

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 627
    Points : 30 692
    Points
    30 692
    Par défaut
    Citation Envoyé par r0d Voir le message
    Ou mieux, d'utiliser un vecteur en protected
    Oui, bien sur, mais le résultat reste quasiment identique: ce n'est toujours pas la classe fille qui s'occupe de l'allocation, vu que c'est la classe vector elle-même qui la gère

    Mon exemple voulait surout rester "aussi proche" que possible de la question d'origine

  7. #7
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 264
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 264
    Points : 6 683
    Points
    6 683
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Mon exemple voulait surout rester "aussi proche" que possible de la question d'origine
    En effet, et tu réponds mieux à la question que moi
    En fait moi je ne réponds pas vraiment à la question, je me contentais "d'élargir le débat"

    Citation Envoyé par koala01 Voir le message
    Oui, bien sur, mais le résultat reste quasiment identique: ce n'est toujours pas la classe fille qui s'occupe de l'allocation, vu que c'est la classe vector elle-même qui la gère
    En fait, j'aurais tendance à penser que le problème n'est finalement pas l'allocation, mais la libération. De même pour RAII (je crois que c'est screetch qui m'avait mis la puce à l'oreille un jour), je trouve que le nom n'est pas bon. Au lieu de "Resource Acquisition Is Initialization", je trouve que ce serait mieux quelque chose du style "Resource Destruction Is Release". En fait c'est un principe général en ingénierie: bien que ce soit lors de l'accélération qu'il faille prévoir la future perte d'énergie, c'est lors du freinage que cette énergie est perdue. Mais bon, là je commence à m'éloigner un peu trop loin je crois

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 65
    Points : 58
    Points
    58
    Par défaut
    Je vous remercie de toutes vos réponses. J'ai bien compris le principe et j'ai maintenant une solution viable.

    Cordialement.

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 14/02/2014, 09h00
  2. Réponses: 5
    Dernier message: 08/04/2013, 13h52
  3. Réponses: 8
    Dernier message: 05/04/2011, 08h06
  4. Réponses: 6
    Dernier message: 13/11/2009, 16h06
  5. Réponses: 2
    Dernier message: 11/12/2007, 14h03

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