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++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    65
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 65
    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
    Invité de passage
    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
    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 expérimenté
    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
    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
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    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;  
    }
    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

  5. #5
    r0d
    r0d est actuellement connecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 292
    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 292
    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
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    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
    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

+ 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