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 :

Appel méthode virtuelle pure dans constucteur


Sujet :

C++

  1. #1
    Membre confirmé

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    Par défaut Appel méthode virtuelle pure dans constucteur
    Bonjour,

    j'ai une classe A. Qui définit une implémentation de plusieurs méthodes.

    Je ne crée jamais d'instance de la classe A. Mais je l'utilise comme un modèle pour les enfants. Dans son constructeur j'ai plusieurs étapes qui doivent-être implémenté chez tous ces enfants.

    Parmi ces étapes j'ai un appel à une méthode de configuration qui diffère pour chacun d'entre-eux.

    Exemple :

    A.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class A 
    {
    	A();
    	virtual conf() = 0;
    }
    A.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    {
    	A::A()
    	{
    		/* Tâche effectué dans tous les fils de A */
     
    		/* Appel méthode qui doit être implémenté par les fils (B et C)*/
    		conf();
    	}
    }
    B.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    class B : public A
    {
    	B();
    	virtual conf() { /* blablabla */;
    }
    Donc en résumé, j'aimerai être sûr que toutes les classes qui hérites de A, implémente et appel la méthode conf().

    Est-ce possible ?

    Merci

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Pour l'obligation d'écrire une fonction conf(), à partir du moment où c'est une fonction virtuelle pure, c'est obligatoire

    Pour l'obligation d'appeler conf(), le plus simple est probablement d'utiliser le pattern NVI

    Par contre, attention à l'appel de fonctions virtuelles dans le constructeur... Puis-je appeler des fonctions virtuelles dans le constructeur (ou le destructeur) ?

  3. #3
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 162
    Points
    17 162
    Par défaut
    En général, le besoin de virtualité dans le constructeur est due à une erreur d'architecture.

    Tu peux utiliser une capsule de configuration, par exemple ainsi construite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    struct configurable{
        void conf();
    };
     
    class conf_capsule{
        configurable& c;
    public:
        conf_capsule(configurable& configurable) : c(configurable) {c.conf();}
        configurable& operator()(){return c;}
        const configurable& operator()() const {return c;}
    };

  4. #4
    Membre confirmé

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    Par défaut
    Par contre, attention à l'appel de fonctions virtuelles dans le constructeur... Puis-je appeler des fonctions virtuelles dans le constructeur (ou le destructeur) ?
    Oui j'avais lu cet article d'où ma question Vu que lorsque le constructeur de la classe parente est appelé la fonction conf() n'existe pas encore.

    Je suis pas sûr que le NVI permettent de m'affranchir de mon problème.

    1. Sachant que je ne peux pas déclarer une méthode virtuelle pure dans mon constructeur.

    2. Que mon constructeur mère va être appelé avant le constructeur fils, donc la spécialisation de conf() n'existera pas encore.

    3. Que je veux forcer l'appel à conf dans le constructeur du fils.

    Le pattern que tu me proposes me permettrai de résoudre mon problème dans une méthode X, mais d'après ce que je comprends elle ne marchera pas pour mon constructeur.

    Merci

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 126
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 126
    Points : 33 033
    Points
    33 033
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    il te suffit de faire ta construction en 2 temps :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Object myObj;
    myObj.init();

  6. #6
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 162
    Points
    17 162
    Par défaut
    Tu peux nous donner plus d'informations "réelles" sur ton contexte de travail?

    Comment sais-tu devoir appeler le confhéritier dans le constructeur de base?

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Cette construction en deux temps peut être forcée à chaque utilisateur en passant par une factory. Ton constructeur est privé, et tu définis une fonction create qui te crée l'objet, puis l'initialise.

  8. #8
    Membre confirmé

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    Par défaut
    leternel :

    En général, le besoin de virtualité dans le constructeur est due à une erreur d'architecture.
    Quelle est l'erreur que je commet ? Je trouvais ma solution plutôt élégante :

    Le fait que l'utilisateur de ma classe ne fait que d'hériter de ma classe A et surcharger la méthode de configuration pour avoir une base fonctionnelle. Ceci évite un appel explicite et ainsi une source d'erreur.

    Je ne suis pas à a recherche d'une solution fonctionnel (finalement en deux appel explicite à conf() je peux faire ce que je veux), mais bien des principes qui apparemment s'oppose à ce que je veux faire.


    Bousk :
    il te suffit de faire ta construction en 2 temps :
    Oui c'est une possibilité, mais cela demande toujours un appel explicite a une méthode d'initialisation. Je trouvais justement que ma première idée permettait de m'affranchir de celle-ci.

    Merci de votre aide / conseils

    p.s. Ce que je veux n'est peut-être tout simplement pas possible en c++

  9. #9
    Membre confirmé

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    Par défaut
    Tu peux nous donner plus d'informations "réelles" sur ton contexte de travail?
    Oui bien sûr, j'ai un système découpé en plugin. Chacun de ces plugins va devoir utiliser diverses classes et les spécialiser selon une configuration présente dans un fichier XML.

    Mon objectif est de faire en sorte que l'utilisateur qui veut spécialiser une classe:
    1. Soit averti qu'il doit implémenter la méthode de configuration (parsing XML)
    2. Aille le moins de chose à faire, j'aimerai m'affranchir de l'appel explicite à conf dans le constructeur qui finalement pourrait-être une source d'erreur.

    Cette construction en deux temps peut être forcée à chaque utilisateur en passant par une factory. Ton constructeur est privé, et tu définis une fonction create qui te crée l'objet, puis l'initialise.
    ça pourrait-être la solution qu'il me faut . J'ai plus le temps (aujourd'hui) d'étudier les factory que je connais pas du tout, mais je fais ça dès la première heure mercredi

  10. #10
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Cette construction en deux temps peut être forcée à chaque utilisateur en passant par une factory. Ton constructeur est privé, et tu définis une fonction create qui te crée l'objet, puis l'initialise.
    Il me semble que JolyLoic entend par la, avoir une classe pour la création de tes objets qui prend en paramètre les conditions de création puis renvoie l'adresse de l'objet créé.
    edit:fautes d'orthographe...

  11. #11
    Membre confirmé

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

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

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Points : 597
    Points
    597
    Par défaut
    Il me semble que JolyLoic entend par la avoir une classe pour la création de tes objets qui prend en paramètre les conditions de création puis renvoie l'adresse de l'objet créée.
    C'est donc cela une factory Donc j'en ai déjà créer une pour le chargement de librairies dynamique.

    Merci à tous pour vos réponses très instructives, je vais partir sur la méthode du double constructeur, avec éventuellement une factory.

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

    Informations professionnelles :
    Activité : aucun

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

    De manière générale, chaque classe ne s'occupe que de l'initialisation de la partie qui lui est propre, et transmet à sa classe mère les informations qui seront nécessaires pour sa propre initialisation, mais il est impossible d'initialiser, dans une classe de base, des informations qui serait relatives à une classe dérivée particulière

    Et c'est normal:

    Quand tu instancies une classe (Derivee) qui dérive d'une classe de base (Base), la première chose qui est créée, c'est un objet de type Base auxquelles viennent s'accoler les informations propres à la classe Derivee.

    Tu ne peux disposer du polymorphisme pour une classe dérivée qu'à partir du moment où l'ensemble des membres de la classe dérivée existent, c'est à dire, dans le corps même du constructeur de cette classe

    Maintenant, rien ne t'empêche d'envisager quelque chose comme
    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
    class Base
    {
        public:
            Base(){init();}
        private:
            virtual void init()
            {
                /* ce qui est propre à l'initialisation de Base */
            }
    };
    class Derivee : public Base
    {
        public:
            Derivee(){init();}
        private:
            virtual void init()
            {
                /* ce qui est propre à l'initialisation de Derivee*/
            }
    };
     
    class SecondeDerivee : public Derivee
    {
        public:
            Derivee(){init();}
        private:
            virtual void init()
            {
                /* ce qui est propre à l'initialisation de SecondeDerivee*/
            }
    };

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 11/10/2013, 12h08
  2. Réponses: 15
    Dernier message: 08/07/2012, 23h49
  3. Réponses: 15
    Dernier message: 05/07/2007, 01h29
  4. Réponses: 23
    Dernier message: 16/03/2007, 20h21
  5. Problème avec une méthode virtuelle pure
    Par Burckel dans le forum C++
    Réponses: 4
    Dernier message: 05/12/2006, 13h00

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