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

Langage C++ Discussion :

Héritage et abstraction


Sujet :

Langage C++

  1. #1
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut Héritage et abstraction
    Bonjour,
    J'ai besoin de votre avis éclairé.

    Pour être plus précis, j'aimerais savoir ce que vous pensez des déclarations suivantes.
    Je ne donne pas d'explications volontairement pour le moment, même si je laisse quelques indices.
    Une fois que quelques réponses auront été donnés, je détaillerai un peu plus.

    À titre informatif, je ne suis pas un débutant, et je suis loin d'être un expert.

    Merci d'avance !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class BaseAbstraite
    {
     
      protected:
        BaseAbstraite();
        BaseAbstraite(BaseAbstraite const&);
        BaseAbstraite& operator = (BaseAbstraite const&);
     
      public:
        virtual
        ~BaseAbstraite() = 0;
     
    }; // class BaseAbstraite

  2. #2
    Membre à l'essai
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juillet 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2012
    Messages : 8
    Points : 12
    Points
    12
    Par défaut
    Je ne sais pas trop ce que tu attends mais je vais essayer.

    Ta déclaration est valable mais il faut implémenter le destructeur même s'il est virtuel pur.

    Ce type de déclaration de classe montre pour moi certaines limites du C++ et entre autre l'impossibilité de déclarer une classe abstraite avec un mot clé comme Abstract (cf. Java),
    ce qui amène à déclarer un destructeur virtuel pur alors que ça n'a aucun sens.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 629
    Points : 10 554
    Points
    10 554
    Par défaut
    Citation Envoyé par SaBe94 Voir le message
    ce qui amène à déclarer un destructeur virtuel pur alors que ça n'a aucun sens.
    Si cela a du sens :
    • virtuel pure veut dire "je ne donne pas l'implémentation à cette méthode, ce sont les classes filles qui doivent le faire".
    • virtuel veut dire "je donne une implémentation par défaut à cette méthode, libre aux classes filles de la redéfinir".


    Édit: @Iradrille: Effectivement, il y a virtuel et virtuel pur


    Et excuse-moi du peu par rapport au Java :
    1. J'ai toujours perdu mon latin entre les herits extends interface class, sans parler des static final et package
    2. Java 1.8 permet de coder des interfaces avec une implémentation par défaut. Comme quoi



    Citation Envoyé par SaBe94 Voir le message
    entre autre l'impossibilité de déclarer une classe abstraite avec un mot clé comme Abstract (cf. Java),
    Certes, mais le compilateur te rappelle à l'ordre si tu essayes d'utiliser une classe abstraite autrement que pour de l'héritage

  4. #4
    Membre expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    739
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Juin 2011
    Messages : 739
    Points : 3 627
    Points
    3 627
    Par défaut
    Citation Envoyé par foetus Voir le message
    Si cela a du sens : virtuel veut dire "je ne donne pas l'implémentation à cette méthode, ce sont les classes filles qui doivent le faire".
    Sauf qu'un destructeur pur n'a pas de sens et devra quand même être défini. Bah oui, la classe fille appel toujours le destructeur de la classe mère. C'est ballot de devoir définir une fonction pure.

    Citation Envoyé par foetus Voir le message
    J'ai toujours perdu mon latin entre les herits extends interface class, sans parler des static final et package.
    C'est quand même un peu pareil avec les fonctions membres qui peuvent avoir static, inline, constexpr, const, volatile, final, une ref-qualifiée, override, virtuelle, noexcept, noreturn (ou autres attributs), delete, probablement bientôt requires (concept), le type de retour à droite, à gauche, decltype et auto. Heureusement qu'on peut séparer par des virgules les prototypes avec un même type de retour... .

  5. #5
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par foetus Voir le message
    Si cela a du sens : virtuel veut dire "je ne donne pas l'implémentation à cette méthode, ce sont les classes filles qui doivent le faire".
    Virtuel veut dire "je donne une implémentation par défaut, les classes dérivées PEUVENT changer l'implémentation".
    Virtuel pur veut dire "je suis autorisé à ne pas donner d'implémentation par défaut (et c'est le cas général), les classes dérivées DOIVENT implémenter la fonction; même si je donne une implémentation par défaut la classe est abstraite et donc non instanciable".

    Si la classe n'a pas d'autres fonctions virtuelles pures, c'est le seul moyen de la rendre abstraite.

    Un constructeur protégé empêche l'instanciation "depuis l’extérieur", mais pas "depuis l'intérieur".
    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
    struct Foo {
       static Foo create() {
          return Foo(); // instanciation possible depuis l'intérieur de la classe
       }
     
    protected:
       Foo() { }
    };
     
    Foo f1 = Foo::create(); // ok
    Foo f2; // erreur - constructeur protégé
     
    struct Bar {
       virtual ~Bar() = 0 { }
     
       static Bar create() {
          return Bar(); // erreur - Bar abstraite
       }
    };
     
    Bar b; // erreur - Bar abstraite

  6. #6
    Membre à l'essai
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Juillet 2012
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juillet 2012
    Messages : 8
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par foetus Voir le message
    Si cela a du sens :
    • virtuel pure veut dire "je ne donne pas l'implémentation à cette méthode, ce sont les classes filles qui doivent le faire".
    • virtuel veut dire "je donne une implémentation par défaut à cette méthode, libre aux classes filles de la redéfinir".
    Je dis que ça n'a pas de sens parce que la règle générale veut que quand je déclare une méthode virtuelle pur, je ne dois pas donner d'implémentation à cette méthode. Les classes filles doivent les redéfinir.

    Mais essaie le code suivant :

    Code C++ : 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
     
    class CAbstract
    {
    public:
    	CAbstract() {};
     
    public:
    	virtual ~CAbstract() = 0;
    };
     
    class CDerived : public CAbstract
    {
    public:
    	CDerived() {};
    public:
    	virtual ~CDerived() {};
    };
     
    int main()
    {
    	{
    		CDerived d;
    	}
    return 0;
    }

    Erreur de compilation. Le compilateur devrait se plaindre de ~CAbstract.

    Pour corriger ce problème il faut donc implémenter le destructeur et ce bien qu'il soit déclaré virtuel pur.

    Je change donc mon code.

    Code C++ : 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
     
    class CAbstract
    {
    public:
    	CAbstract() {};
     
    public:
    	virtual ~CAbstract() = 0 { cout << "CAbstract destructor" << endl; };
    };
     
    class CDerived : public CAbstract
    {
    public:
    	CDerived() {};
    public:
    	virtual ~CDerived() { cout << "CDerived destructor" << endl; };
    };
     
    int main()
    {
    	{
    		CDerived d;
    	}
    return 0;
    }

    Là ça compile et je devrais voir comme trace sur ma console : "CDerived destructor" et "CAbstract destructor".

    Pour moi, en faisant cela on casse deux principes :
    1. Ne jamais implémenter une méthode virtuelle pure

    1. Ne jamais appeler une méthode virtuelle pure


    Au final, on déclare le destructeur virtuel pur uniquement quand on souhaite que notre classe soit non instanciable et qu'on ne voit pas quelle autre méthode peut être déclarée virtuelle pure.

    Ce n'est donc qu'une astuce parce qu'il n'existe pas un mot clé pour déclarer la classe non instanciable.

  7. #7
    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
    a- Constructeur de copie et opérateur d'affectation devraient être purement et simplement supprimés -> "= delete", ou hérite de boost::noncopyable (qui reste ma façon de faire préférée).
    b- Le destructeur virtuel pur doit quand même être défini comme cela a été signalé
    c- Qu'il y ait un constructeur par défaut ou non, qu'il soit public ou protégé ne changera rien : la classe est abstraite et seules les filles pourront faire appel au constructeur.
    d- Le nom est tout pourri : il ne transporte aucune sémantique ; mais je soupçonne que pour l'instant c'est fait pour
    e- "protected" est devenu un red flag chez moi du coup je cherche systématiquement s'il y a des données avec cette visibilité. L'objectif de l'encapsulation, c'est de garantir l'invariant d'une classe. Or quand il y a des données protégées, cela veut dire que les classes filles devront faire attention à continuer à garantir les invariants de la classe mère lorsqu'elles iront toucher aux données protégées. Même chose avec les fonctions protégées. J'ai aujourd'hui envie de dire qu'une fonction ne devrait pas être autorisée à être protégée si elle ne peut pas garantir les invariants tout comme les fonctions publiques. [Mais je m'égare, "protected" a été employé pour tout autre chose, certes inutile -> c-]

    EDIT:
    PS: si vous cherchez à savoir comment rendre une classe non-instanciable, la seule façon c'est de la rendre abstraite, et seule une fonction membre virtuelle (aka méthode -- qui englobe officiellement les 3 mots en C++) pure permet cela. Il y a une définition mal formulée dans la norme à ce sujet.
    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...

  8. #8
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bien, merci pour vos réponses.
    Le but était de voir ce qui saute aux yeux avant d'orienter la discussion, du coup j'ai obtenu à peu près les réponses auxquelles je m'attendais…
    Mais aussi des choses plus intéressantes.

    Le code présenté est censé représenter une classe dont la seule finalité est d'être au sommet d'une hiérarchie.
    Par exemple, une classe XMLElement qui permet de manipuler n'importe quel élément XML, peu importe que ce soit une balise, du texte, un commentaire, etc., mais qui, en soit (j'entends, seule), ne sert à rien.

    Une telle classe n'a pas vocation à être instanciée.
    Pour cela, il y a a priori deux moyens :
    1. ne laisser aucun constructeur public ;
    2. rendre la classe abstraite (via une fonction membre virtuelle pure).
    Sauf que comme l'a très bien fait remarquer @Iradrille, la première méthode permet l'instanciation « depuis l'intérieur », à savoir depuis la classe elle-même, les classes filles (constructeurs protégés), ou même les amis.
    Pour autant, si le programmeur n'écrit pas de bêtises, cela n'a pas vraiment d'importance. (Si ?)

    [EDIT]Après réflexion, le programmeur original ne maîtrise pas les classes filles écrites par d'éventuels utilisateurs, qui pourraient tout à fait accéder aux constructeurs protégés.
    Oubliez ma dernière réflexion[/EDIT]

    Ceci dit, est-ce une erreur, une faute, de combiner les deux ?
    Certes, dès lors qu'une classe est abstraite, aucun constructeur ne peut être appelé directement, peu importe sa visibilité.
    Il est donc inutile de chercher à les masquer ; mais pour autant, ce n'est pas interdit.

    Donc en gros, c'est cela ma question.
    Est-ce que c'est :
    • « inutile, mais à la rigueur pourquoi pas » ;
    • une très bonne idée ;
    • une faute de programmation ;
    • une erreur de conception ;
    • quelque chose de pas si mauvais, mais à éviter tout de même ;
    • etc.


    À la réflexion, j'ai le sentiment que le vrai problème est posé dans la discussion proposée par @Luc Hermitte.
    (Après tout, avant de se rendre compte que la réponse était 42, il a d'abord fallu trouver la (vraie) question…)
    La discussion est très intéressante, et complètement dans le sujet selon moi.
    Je ne comprends pas trop pourquoi le lien a été retiré du post…

  9. #9
    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
    Mon lien discutait de la définition des classes abstraites selon le standard -- quand j'avais regardé le bestio il y a une 15aine d'années, j'avais trouvé la formulation mauvaise. Cherche donc sur google: "Terminologie Classe abstraite fr.comp.lang.c++ et luc hermitte", tu retrouveras de suite le fil de discussion. Plusieurs services mettent à disposition les discussions sur usenet -- et la façon de faire de google-groups est devenue franchement peu ergonomique, ce qui est bien dommage.

    Pour ta question, je n'aime pas le constructeur protégé car de toutes façons la classe n'est pas instanciable et donc cela n'apporte rien de plus. Et aujourd'hui le "protected" attire mon attention, ce qui est généralement un mauvais indice. Hier j'aurai dis avec peu d'hésitation "go for protected". Demain, je ne sais pas ce que je dirai.

    PS: il existe déjà plein de libs FOSS plus ou moins abouties qui savent décoder des XML -- je regarderai en priorité celles de chez CodeSynthesis. Je dirai de d'abord partir dans cette direction vu la quantité de boulot, souvent inintéressant, qu'il y a à faire sur le sujet.
    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...

  10. #10
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    Pour autant, si le programmeur n'écrit pas de bêtises, cela n'a pas vraiment d'importance. (Si ?)
    Si on part sur ce principe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // ne pas instancier svp, cette classe est abstraite !
    struct Foo { };
    Après du moment que ta classe est abstraite, avoir un constructeur protégé ou pas ne change strictement rien.

    Et c'est pareil pour les constructeurs par copie et opérateur d'affectation : si tu veux rendre la classe non copiable supprimes les ( = delete ou si ton compilo ne supporte pas cette syntaxe, laisse les privés sans implémentation, ils n'ont pas de raison d'être protégés).
    Il est aussi préférable d'hériter de boost::noncopyable (ou équivalent) : ça prend une ligne de moins ça explicite l'intention.

  11. #11
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bon, quelques remarques que je n'ai pas eu le temps de faire tout à l'heure…

    Citation Envoyé par SaBe94 Voir le message
    Ta déclaration est valable mais il faut implémenter le destructeur même s'il est virtuel pur.
    Citation Envoyé par Luc Hermitte Voir le message
    b- Le destructeur virtuel pur doit quand même être défini comme cela a été signalé
    Comme je le disais, ce ne sont que des déclarations.
    L'implémentation n'a aucune importance dans le problème qui nous occupe ici.

    Citation Envoyé par Luc Hermitte Voir le message
    a- Constructeur de copie et opérateur d'affectation devraient être purement et simplement supprimés -> "= delete", ou hérite de boost::noncopyable (qui reste ma façon de faire préférée).
    Citation Envoyé par Iradrille Voir le message
    Et c'est pareil pour les constructeurs par copie et opérateur d'affectation : si tu veux rendre la classe non copiable supprimes les ( = delete ou si ton compilo ne supporte pas cette syntaxe, laisse les privés sans implémentation, ils n'ont pas de raison d'être protégés).
    Il est aussi préférable d'hériter de boost::noncopyable (ou équivalent) : ça prend une ligne de moins ça explicite l'intention.
    Encore une fois, je n'ai mis que les déclarations.
    Il n'y a aucune raison que la classe ne soit pas copiable ; du moins, les classes filles.
    Le constructeur par copie est protégé pour la même raison que le constructeur par défaut.
    Quant à l'opérateur d'affectation… je peux me tromper mais il me semble que l'opérateur d'affectation ne doit pas être plus visible que le constructeur par copie.
    (Si cela n'amène pas à débat, je serais intéressé de lire votre avis sur le sujet.)

    Bien sûr, dupliquer un objet qui ne contient aucune information n'a pas vraiment de sens ; on obtiendrait exactement le même résultat en en créant un tout neuf.
    D'un autre côté, laisser deux possibilités de faire la même chose, ce n'est pas un drame.
    Normalement, un constructeur par copie appelle les constructeurs par copie des classes parentes, et peu importe s'il ne font rien.
    Idem pour l'opérateur d'affectation.

    Citation Envoyé par Luc Hermitte Voir le message
    d- Le nom est tout pourri : il ne transporte aucune sémantique ; mais je soupçonne que pour l'instant c'est fait pour
    Comment ça il ne transporte aucune sémantique ???
    C'est un exemple abstrait d'une classe abstraite.
    Que voulez-vous de plus comme sémantique ?
    (Comment ça ma vanne est toute pourrie ??? )

    Citation Envoyé par Luc Hermitte Voir le message
    PS: il existe déjà plein de libs FOSS plus ou moins abouties qui savent décoder des XML -- je regarderai en priorité celles de chez CodeSynthesis. Je dirai de d'abord partir dans cette direction vu la quantité de boulot, souvent inintéressant, qu'il y a à faire sur le sujet.
    Celle-là, je l'avais vue venir…
    XMLElement, c'était juste un exemple pour donner un peu de concret à toute cette abstraction.

    Pour être honnête, cela fait un petit moment que je me pose cette question (des constructeurs non publics d'une classe abstraite), mais je ne me souviens plus vraiment de quels objets l'ont soulevée.
    Et la première chose à laquelle j'ai pensé en écrivant le post, c'était les éléments XML.
    Enfin plutôt les élément HTML en réalité, mais bref…
    Je te rassure, je n'ai absolument pas l'intention de me lancer dans le développement de bibliothèques de décodage/analyse XML.

  12. #12
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Citation Envoyé par Luc Hermitte Voir le message
    Pour ta question, je n'aime pas le constructeur protégé car de toutes façons la classe n'est pas instanciable et donc cela n'apporte rien de plus. Et aujourd'hui le "protected" attire mon attention, ce qui est généralement un mauvais indice. Hier j'aurai dis avec peu d'hésitation "go for protected". Demain, je ne sais pas ce que je dirai.
    Hum…
    Donc en gros, protected a été inventé pour laisser un intermédiaire entre public et private, mais au final c'est beaucoup plus compliqué à utiliser.
    S'il y a des discussions sur le sujet, je suis preneur.

    Je commence sérieusement à m'interroger sur l'emploi de cette visibilité…

    Quoi qu'il en soit, ce fut très instructif.
    Merci.

  13. #13
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Citation Envoyé par Steph_ng8 Voir le message
    Encore une fois, je n'ai mis que les déclarations.
    Il n'y a aucune raison que la classe ne soit pas copiable ; du moins, les classes filles.
    Le constructeur par copie est protégé pour la même raison que le constructeur par défaut.
    Quant à l'opérateur d'affectation… je peux me tromper mais il me semble que l'opérateur d'affectation ne doit pas être plus visible que le constructeur par copie.
    (Si cela n'amène pas à débat, je serais intéressé de lire votre avis sur le sujet.)
    Si la classe est abstraite, on ne pourra pas copier une instance (puisqu'on ne pourra pas avoir d'instance) : il faudra passer par une classe dérivée.
    Il n'y à aucun intérêt à mettre le constructeur par copie / opérateur d'affectation protégé (en tout cas si ceux par défaut suffisent, dans le cas ou il faut les redéfinir, protégé ou public ne change rien, et je serais surement tenté de les mettre protégé).

    Le problème de constructeurs et d'opérateurs d'affectations non publiques c'est que c'est une forme utilisé généralement pour dire que la classe est non copiable.

    Si la classe est copiable et que les implémentations par défaut suffisent, laisse les publiques.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class BaseAbstraite {
      public:
        virtual ~BaseAbstraite() = 0 { } 
    }; // class BaseAbstraite

  14. #14
    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
    A partir du moment où il y a un héritage, syntaxiquement, il est impossible d'affecter sans sortir des feintes pas possibles. Copier ne marche pas non plus si tu es transtypes (genre, tu ne peux pas copier un Fils2 en Fils1). Au mieux, on a le clonage.
    Seulement, sémantiquement, il y a très rarement besoin de dupliquer quand on est au milieu de hiérarchies polymorphes. De tels objets sont souvent des entités, et copier des entités n'a aucun sens.

    Maintenant, quand tu prends des exemples d'éléments XML, ces derniers ne sont pas des entités classiques. Ils ont une sémantique bâtarde dans la mesure où il arrive que l'on veuille dupliquer des noeuds. Cela vient du fait que de tels objets sont avant tout de la donnée et rien d'autre: leur côté service est extrêmement restreint. Voire, s'ils se spécialisent selon le métier (quand on fait du binding XML <-> C++), il arrive même que l'on veuille procéder à des copies et des affectations pour raisons de simplicité d'utilisation chez ceux qui ne pratiquent pas le clonage. Et là, il faut sortir l'artillerie lourde à base d'idiome enveloppe-lettre ou autres feintes dans le genre.

    Bref, ce type de hiérarchies reste une exception. Une classe abstraite/interface par défaut n'a pas à être copiable ni affectable.
    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...

  15. #15
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Je vois.
    Merci de m'avoir rappelé ces « préceptes » important.

  16. #16
    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
    Citation Envoyé par Luc Hermitte Voir le message
    Bref, ce type de hiérarchies reste une exception. Une classe abstraite/interface par défaut n'a pas à être copiable ni affectable.
    Plus qu’une exception, c’est presque une erreur de design en fait. C’est un variant qui serait plus approprié. Mais ça ne serait pas DOM-compatible, qui impose un héritage...

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

Discussions similaires

  1. [PHP 5.3] Abstract méthode en héritage
    Par Général03 dans le forum Langage
    Réponses: 3
    Dernier message: 21/10/2011, 11h31
  2. Abstract et héritage
    Par nicdo77 dans le forum Langage
    Réponses: 4
    Dernier message: 18/11/2009, 14h05
  3. [Postgres] Héritage + Clés
    Par k-reen dans le forum PostgreSQL
    Réponses: 6
    Dernier message: 21/05/2003, 16h37
  4. Abstract VS virtual
    Par LE CHAKAL dans le forum Langage
    Réponses: 2
    Dernier message: 29/08/2002, 17h50
  5. Héritage entre Forms
    Par BarBal dans le forum Composants VCL
    Réponses: 7
    Dernier message: 29/08/2002, 17h44

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