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 :

[SURGHARGE][HERITAGE] Probleme compilation


Sujet :

C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 129
    Points : 68
    Points
    68
    Par défaut [SURGHARGE][HERITAGE] Probleme compilation
    Voilà, j'ai fais trois TP en C++ et le dernier me faisait travailler l'héritage et la surcharge.

    Voici le main proposé en énoncé :

    c_base_pile.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
     
    #include "c_base_pile.h"
     
    std::ostream& operator << (std::ostream&,const PileDeChar&); 
     
    int main(void)
    {
        PileDeChar* ptPile;
        pileFIFO fifo;
        pileLIFO lifo;
     
        ptPile=&fifo;
        *ptPile < '1' < 'A';
        cout<<"pile1 = "<<*ptPile<<endl;
     
        char i='3';
        *ptPile > i;
        cout<<"pile2 = "<<*ptPile<<", i = "<<i<<endl;
     
        ptPile=&lifo;
        *ptPile < '5' < 'C';
        cout<<"pile3 = "<<*ptPile<<endl;
        *ptPile > i;
        cout<<"pile4 = "<<*ptPile<<", i = "<<i<<endl;
     
    system("pause");
     
    return 0;
    }
    Partie que j'ai ajouté au main
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    std::ostream& operator << (std::ostream& flux, const PileDeChar& pile) 
    { 
        pile.Affichage(flux); 
        return flux; 
    }

    ===========================================
    Maintenant voici ce que j'ai écrit :

    c_base_pile.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
     
    #include <iostream.h>
     
    class PileDeChar {
          protected:
          unsigned int mMax; /*Taille de la pile crée,num case libre*/
          char *mPile; /*Tableau alloué dynamiquement*/
          int mSommet;
     
          public:
     
     
          PileDeChar();
          PileDeChar(signed int);
          PileDeChar(const PileDeChar&);
          ~PileDeChar();
          int CompterElements() const;
          int LitmMax() const;
          void AfficherPile() const;
          bool EmpilerElem(char);
          char RenvoiElement(signed int) const;
          PileDeChar& operator < (char);
          virtual PileDeChar& operator > (char&)=0;
          friend std::ostream& operator << (std::ostream&, const PileDeChar&);
          virtual void Affichage(std::ostream&) const; 
     
    };
     
    class pileFIFO:public PileDeChar {
     
          public:
          virtual char DesempilerElem();
          pileFIFO& operator > (char&);
          virtual void Affichage(std::ostream&);
    };
     
    class pileLIFO:public PileDeChar {
     
          public:
          virtual char DesempilerElem();
          pileLIFO& operator > (char&);
          virtual void Affichage(std::ostream&); 
    };

    c_base_pile.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
    103
    104
    105
    106
    107
    108
     
    #include <iostream.h>
    #include "c_base_pile.h"
     
    PileDeChar::PileDeChar()
    {
     mMax=100;
     mSommet=0;
     mPile=new char[100];
     cout<<"Construction effectuee !"<<endl;          
    }
     
    PileDeChar::PileDeChar(signed int taille)
    {
     mMax=taille;
     mSommet=0;
     mPile=new char[taille];         
      cout<<"Construction effectuee !"<<endl;
    }
     
    PileDeChar::PileDeChar(const PileDeChar& copie)
    {
     size_t i=0;
     mMax=copie.mMax;
     mSommet=copie.mSommet;
     mPile=new char[mMax];
     while(i<mSommet)
     {
                  mPile[i]=copie.mPile[i++];
     }
      cout<<" Copie Pile effectuee!"<<endl;
    }
     
    PileDeChar::~PileDeChar()
    {
               delete(mPile);
    cout<<"Destruction effectuee !"<<endl;
    }      
     
    int PileDeChar::CompterElements() const    
    {
        if (mPile!=NULL)    
           return mSommet;
        else return -1;
    }
     
    int PileDeChar::LitmMax() const
    {
        if (mPile!=NULL)    
           return mMax;
        else return -1;
    }
     
    void PileDeChar::AfficherPile() const
    {
         size_t i=0;
         if(mSommet==0)
         cout<<"Il n'y a rien a afficher !"<<endl;
         else
         {
         while(i<mSommet) cout<<"["<<mPile[i++]<<"] ";
         cout<<endl;
         }
    }
     
    char PileDeChar::RenvoiElement(signed int i) const
    {
         if ((mPile!=NULL)&&((i>=0)&&(i<LitmMax())))
           return mPile[i];
         else
         {cout<<"ERREUR, PILE VIDE, MAUVAIS INDICE"<<endl;
          return 0;}
     
    }
     
    bool PileDeChar::EmpilerElem(char elem)
    {
         bool reussi=false;
         if(mSommet<LitmMax())
         {
                         mPile[mSommet++]=elem;
                         reussi=true;
         }
         else 
         reussi=false;
         return reussi;
    }
     
    PileDeChar& PileDeChar::operator<(char elem)
    {
     
         if(mSommet<LitmMax())
         {
                   mPile[mSommet++]=elem;
         }
         return *this;   
     
    }
     
    //void PileDeChar:: operator > (char a){cout<<"erreur"<<endl;}
     
    void PileDeChar:: Affichage(std::ostream& flux) const
        { 
            int i=0;
            while(i<mSommet)
            flux << mPile[i++];
     
        }
    fifo.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
     
    #include <iostream.h>
    #include "c_base_pile.h"
     
     
    char pileFIFO::DesempilerElem()
    {
         char temp;
         int i=0;
         if((mSommet>0)&&(mSommet<=LitmMax()))
         {
          temp=RenvoiElement(0);
          while(i<mSommet)
          {
                     mPile[i]=mPile[i+1];
                     i++;
          }
          mSommet--;
          return temp;
         }     
         else
         {
             cout<<"ERREUR : IL N'Y A RIEN A RECUPERER"<<endl;
         return 'e';
         }
    }
     
    pileFIFO& pileFIFO::operator > (char &a)
    {
         int i=0;
         if((mSommet>0)&&(mSommet<=LitmMax()))
         {
          a=RenvoiElement(0);
          while(i<mSommet)
          {
                     mPile[i]=mPile[i+1];
                     i++;
          }
          mSommet--;
     
         }     
         else
         cout<<"ERREUR : IL N'Y A RIEN A RECUPERER"<<endl;
     
        return *this;
    }
     
    void pileFIFO::Affichage(std::ostream& flux)
        { 
          int i=0;
            while(i<mSommet)
            flux << mPile[i++];
            cout<<"fifo"<<endl;   /* ME PERMET DE SAVOIR QUELLE FONCTION AFFICHAGE EST APPELEE*/
        }

    lifo.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
    #include <iostream.h>
    #include "c_base_pile.h"
     
    char pileLIFO::DesempilerElem()
    {
         if((mSommet>0)&&(mSommet<=LitmMax()))
         {
         mSommet--;
         return RenvoiElement(mSommet);
         }
         else
         {
             cout<<"ERREUR : IL N'Y A RIEN A RECUPERER"<<endl;
         return 'e';
         }
    }
     
    pileLIFO& pileLIFO::operator > (char &a)
    {
         if((mSommet>0)&&(mSommet<=LitmMax()))
         {
         mSommet--;
         a=RenvoiElement(mSommet);
     
         }
         else
         cout<<"ERREUR : IL N'Y A RIEN A RECUPERER"<<endl;
     
        return *this;
    }
     
    void pileLIFO::Affichage(std::ostream& flux) 
        { 
          int i=0;
            while(i<mSommet)
            flux << mPile[i++];
            cout<<"fifo"<<endl; /* ME PERMET DE SAVOIR QUELLE FONCTION AFFICHAGE EST APPELEE*/
        }

    Mon problème est le suivant : aucune erreur sous DevC pp a priori. Mais des fois j'ai un warning qui apparait lors de la compilation(sans execution)(CTRL+F9) :
    3 F:\Dev-Cpp\projet\C++\tp3\c_base_pile.h [Warning] `class PileDeChar' has virtual functions but non-virtual destructor
    28 F:\Dev-Cpp\projet\C++\tp3\c_base_pile.h [Warning] `class pileFIFO' has virtual functions but non-virtual destructor
    .....
    Et la si je recompile et lance le programme(F9) le warning disparrait et le programme fonctionne.

    Voilà donc j'aimerais avoir votre avis éclairé sur mon programme. Merci d'avance.

    PS : j'ai utilisé protected car je ne voulais pas faire de méthodes d'accés. Je sais que j'aurais du mais cette histoire d'héritage me tracassait...

    Merci encore

  2. #2
    Membre averti Avatar de xxiemeciel
    Inscrit en
    Juin 2005
    Messages
    371
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 371
    Points : 352
    Points
    352
    Par défaut
    Salut,

    J'ai regardé rapidement, si tu as un warning c'est tout simplement parceque ton destructeur n'est pas virtuel. Le destructeur est la seule methode qui si el est virtuel va s'appeler en cascade.

    Image le cas suivant, tu crée un PileFIFO et tu la nomme en tant que type PileDeChar

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PileDeChar* pile = new PileFIFO(//params);
    alors quand tu detruira ton objet avec delete il faut appeler le destructeur de PileFIFO puis ensuite PileDeChar pour detruire tout les membre ce qui se fais en declarant les destructeur virtual. Dans ton cas ce n'est pas trop genant puisque il n'y a rien a detruire dans PileFIFO. Mais dans certains cas ca peut faire des memory leak donc le compilateur met un warning pour prevenir du danger potentiel.

    Sinon j'ai juste regardé les header files et je n'ai pas analyser tes code de fonctions donc a toi de voir si ca fonctionne correctement avec des tests.

    XXiemeciel
    XXiemeciel

  3. #3
    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
    C'est un petit peu plus gênant que ça quand même.
    Dans le cas suivant : une classe mère A et une classe B dérivant de A . Le destructeur de A n'étant pas 'virtuel'
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class A
    {
    public: 
      ~A();
    };
     
    class B : public A
    {
    };
    Détruire une instance de B, via un pointeur sur A implique un comportement indéfini.
    Donc ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    A * a = new B();
    delete a;
    peut amener, en fonction des compilateurs un plantage complet et non juste une fuite de mémoire.
    En pratique, si une classe défini une fonction membre comme 'virtual', c'est que le concepteur pense qu'elle est suceptible d'être dérivée. Son destructeur devrait donc, lui aussi, être déclaré virtuel.

  4. #4
    Membre éprouvé Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Points : 1 122
    Points
    1 122
    Par défaut
    En C++, il n'y a pas moyen de finaliser une classe. C'est à dire d'interdire sa dérivation. Enfin il me semble.

    Donc, comme tu ne peux pas être sûr qu'une classe ne sera pas dérivée, un constructeur est obligatoirement virtuel.

    Pour les raisons qui ont été données.

  5. #5
    Membre averti
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Points : 353
    Points
    353
    Par défaut
    Salut,

    J'avais vu un moyen d'empecher une classe d'être dérivée:
    en la faisant hériter d'une classe dont le constructeur est privé, et qui déclare la classe en question comme amie (afin qu'elle seule puisse y accéder).
    http://www.research.att.com/~bs/bs_f...#no-derivation

    Je ne sais pas ce que ça vaut, mais voilà


    ps: j'imagine que
    un constructeur est obligatoirement virtuel.
    tu voulais dire "destructeur"
    And still we will be here, standing like statues ...

  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
    Citation Envoyé par Caine
    Donc, comme tu ne peux pas être sûr qu'une classe ne sera pas dérivée, un constructeur est obligatoirement virtuel.
    Je crois que je n'ai pas tout suivi là. Un constructeur, ça ne peut pas être virtuel.
    Maintenant, des cas où on ne souhaite pas avoir de destructeur virtuel sont nombreux.
    D'ailleurs, ne pas posseder de destructeur virtuelle n'empêche pas la dérivation. Cela empêche juste la destruction d'une instance de classe dérivée via un pointeur sur la classe de base.

  7. #7
    Membre averti
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Points : 353
    Points
    353
    Par défaut
    Maintenant, des cas où on ne souhaite pas avoir de destructeur virtuel sont nombreux. D'ailleurs, ne pas posseder de destructeur virtuelle n'empêche pas la dérivation. Cela empêche juste la destruction d'une instance de classe dérivée via un pointeur sur la classe de base.
    Et c'est quoi l'intérêt ? A mon avis, ça ne coute rien de mettre un destructeur virtuel, et ça évite bien des problèmes si quelqu'un décide d'hériter de la classe derrière toi ... A moins que tu empêches la dérivation (par exemple avec le système de lock que j'ai donné juste avant) ...
    And still we will be here, standing like statues ...

  8. #8
    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 grand principe de développement du langage C++, c'est que tu ne payes que ce que tu utilise. Il y a d'autre langage, Java par exemple, où toute classe est dérivable par défaut (hors mention explicite) et ou toute fonction est redefinissable.
    Si ça ne servait à rien, les destructeurs seraient tous virtuel par défaut.

    Un des interêts c'est de ne pas payer la place d'une vtable.
    Un exemple tiré du soft que je développe. Tu crées une classe Point avec 2 coordonnées entières. La taille d'une instance de cette classe c'est 8 octets (mes entiers valent 4 octets chacun).
    Si tu définis un destructeur virtuel, nécessairement, le compilateur rajoutera à la structure un pointeur vers la table d'indirection des fct (vptr). Du coup, pour stocker un point, j'ai besoin de 12 octets (sur une archi 32 bits). D'où un accroissement de taille de 150%, tout cela pour rien, car je ne souhaite pas surcharger cette structure.

  9. #9
    Membre averti
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Points : 353
    Points
    353
    Par défaut
    Ah oui, OK pour ce cas la

    Mais c'est dommage que le C++ ne propose aucun mecanisme standard pour empecher la dérivation d'une classe alors ... Parceque le comportement sera +- indéfini si quelqu'un hérite de ta classe Point.

    Et j'imagine que la solution du lock prend un peu de place aussi
    A moins que (pour ne pas froisser Selenite ) le compilateur détecte que cette classe mère est vide, donc qu'elle a seulement un but structurel, et donc qu'il ne change pas le code généré .... ce qui serait plutôt sympa !
    And still we will be here, standing like statues ...

  10. #10
    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
    Mais rien de t'empêche d'hériter de mon point. Un fois encore, la seule chose qui est interdite, c'est de détruire une instance dérivée via un pointeur sur la classe de base.
    Le 'virtual' n'est en rien nécessaire au bon chaînage des destructeurs lorsque tu detruis une instance allouée dynamiquement via un pointeur dont le type statique correspond au type dynamique.
    N'oublie pas d'ailleurs qu'en C++, il y a plusieurs type d'héritage et tu peux légalement faire de l'héritage d'implémentation (privé) à partir de types qui ne possèdent pas de destructeurs virtuels. Et dans ce cas, tu ne cours jamais le risque de comportement indéfini (puisque B n'est pas un A, même s'il hérite de l'implémentation).

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Et en général, mettre ou non un destructeur virtuel donne justement une bonne indication sur le fait que l'on souhaite ou non voir la classe être dérivée publiquement.
    Bien qu'idéalement il faille aussi l'indiquer clairement dans la doc.

  12. #12
    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 moyen de rendre non dérivables des classes. Mais c'est compliqué pour pas grand chose, et contournable par les initiés.

    J'ai quantités de classes qui ne sont pas prévues pour être "dérivées polymorphiquement" (désolé pour le néologisme) et elles ne contiennent jamais de destructeur virtuel. En revanche dans la doc, je précise ses sémantiques et rappelle qu'elle n'est pas prévue pour être dérivée. Le jour où cela deviendrait vraiment nécessaire, du refactoring sera à prévoir (au minimum rajouter un virtuel au destructeur, plus prévoir les fonctions à redéfinir).
    (J'ai aussi des classes, de base, à destructeur protégé non virtuel)
    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...

  13. #13
    Membre éprouvé Avatar de Caine
    Inscrit en
    Mai 2004
    Messages
    1 028
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 028
    Points : 1 122
    Points
    1 122
    Par défaut
    Oui, bien sûr je parlais du destructeur.

    C'est ça l'embêtant quand on se relit, on lit ce que l'on a voulu écrire et non ce qu'on a écris

    En plus, très longue journée hier

    En C++, à part par documentation ou avec une astuce de sioux, il est impossible d'interdire la dérivation. C'est bien dommage.

  14. #14
    Membre averti
    Avatar de bigquick
    Profil pro
    Inscrit en
    Août 2002
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 356
    Points : 353
    Points
    353
    Par défaut
    Et en général, mettre ou non un destructeur virtuel donne justement une bonne indication sur le fait que l'on souhaite ou non voir la classe être dérivée publiquement.
    C'est juste, j'y avais pas pensé Mais c'est clair qu'il faut clairement l'indiquer dans la doc alors.

    Mais rien de t'empêche d'hériter de mon point. Un fois encore, la seule chose qui est interdite, c'est de détruire une instance dérivée via un pointeur sur la classe de base.
    Je n'ai jamais dit le contraire, mais je vois mal un commentaire dans la doc "vous pouvez heriter de cette classe, mais surtout lorsque vous l'instanciez sur le tas, utilisez un pointeur vers le type dérivé". Pour moi, ce genre de choses mènera à terme à des erreurs bizarres qui prenront potentiellement du temps à identifier. A mon avis, mieux faut préciser qu'il ne faut pas hériter de la classe en question.

    N'oublie pas d'ailleurs qu'en C++, il y a plusieurs type d'héritage et tu peux légalement faire de l'héritage d'implémentation (privé) à partir de types qui ne possèdent pas de destructeurs virtuels.
    Pour moi c'est super proche de l'aggrégation, mais ça rajoute une couche d'héritage inutile. Est-ce qu'il y a des avantages à utiliser l'héritage privé ?

    Sinon juste par curiosité Luc,
    Mais c'est compliqué pour pas grand chose, et contournable par les initiés.
    comment peux tu faire pour contourner le type de verrou présenté dans le lien ? (si par exemple cette classe vérouillée fait partie d'une bibliothèque que tu ne peux -à priori- pas modifier)

    Enfin donc d'après vous, le mieux est de laisser la liberté d'hériter (pas de verrou), mais en précisant dans la doc qu'il est délicat de le faire ?
    Voilà, merci, et euh désolé pour la pollution dans le post ...
    And still we will be here, standing like statues ...

  15. #15
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par bigquick
    J'avais vu un moyen d'empecher une classe d'être dérivée:
    en la faisant hériter d'une classe dont le constructeur est privé
    Il manque un mot important: il faut heriter virtuellement de cette classe, sinon ca ne fonctionne pas. La caracteristique sur laquelle cette technique se base est que toutes les classes dont elle herite virtuellement doivent etre construite par la classe la plus derivee (vu qu'on peut avoir plusieurs chemin d'heritage, il ne faut pas qu'elle soit construite plusieurs fois).
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  16. #16
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par bigquick
    Sinon juste par curiosité Luc,
    Mais c'est compliqué pour pas grand chose, et contournable par les initiés.
    comment peux tu faire pour contourner le type de verrou présenté dans le lien ? (si par exemple cette classe vérouillée fait partie d'une bibliothèque que tu ne peux -à priori- pas modifier)
    Je suis aussi curieux.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  17. #17
    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
    Ouah, ça commence à être compliqué
    Tant qu'à parler des héritages et des fonctions virtuelles, comment cela se passe quand les 2 classes sont en plus des classes template ? Il y a aussi création de la vtable ?

  18. #18
    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
    Ouah, ça commence à être compliqué
    Tant qu'à parler des héritages et des fonctions virtuelles, comment cela se passe quand les 2 classes sont en plus des classes template ? Il y a aussi création de la vtable ?
    La table d'indirection n'est crée que si elle est utile. Un objet qui ne définie pas, ou n'hérite pas de fonctions virtuelles ne possèdent pas de vtable. Qu'il soit une instance d'un instance de template, ou non.

  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 Jean-Marc.Bourguet
    Citation Envoyé par bigquick
    Sinon juste par curiosité Luc,
    Mais c'est compliqué pour pas grand chose, et contournable par les initiés.
    comment peux tu faire pour contourner le type de verrou présenté dans le lien ? (si par exemple cette classe vérouillée fait partie d'une bibliothèque que tu ne peux -à priori- pas modifier)
    Je suis aussi curieux.
    La méthode bourrin, qui en théorie fourni un comportement indéfini, mais qui marche avec pas mal de compilo
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define private protected
    #include <La classe à étendre>
    #undef private
    class DD : public <La class à étendre>
    {};

  20. #20
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par VoidSeer
    La méthode bourrain, qui en théorie fourni un comportement indéfini, mais qui marche avec pas mal de compilo
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #define private protected
    #include <La classe à étendre>
    #undef private
    class DD : public <La class à étendre>
    {};
    Ca depend du fait qu'on est les premiers a include le fichier declarant la classe a etendre, ca rends protected tout ce qui est prive dans les autres classes definies directement ou indirectement par ce fichier, on se retrouve avec du comportement indefini si un en-tete standard fait partie de ce qui est inclus indirectement, j'en passe vraissemblablement.

    C'est pas le genre de methodes que j'appellerais "contournables par les inities", mais bourrain c'est bien le bon mot :-)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [DEBUTANT] problem compilation eclipse
    Par roninou dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 14/01/2005, 15h59
  2. [JAR]Probleme compilation avec jdom
    Par ronaldgis dans le forum Eclipse Java
    Réponses: 4
    Dernier message: 04/08/2004, 11h31
  3. [C++] Heritage - Probleme constructeur
    Par yanndublanche dans le forum Débuter
    Réponses: 2
    Dernier message: 04/08/2004, 10h17
  4. probleme compilation classe avec Borland c++ compiler 5.5
    Par softblue dans le forum Autres éditeurs
    Réponses: 2
    Dernier message: 17/06/2004, 15h16
  5. [Debian] problème compilation jbuilder 9...
    Par Ancien_Do.Urden dans le forum JBuilder
    Réponses: 5
    Dernier message: 20/03/2004, 15h02

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