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 :

Heritage et méthode virtuelle dans constructeur


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 12
    Par défaut Heritage et méthode virtuelle dans constructeur
    Bonjour à tous,

    Je bloque sur un problème de conception pour appeler une méthode virtuelle depuis un constructeur. Voici mon cas de figure :
    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
     
    class mere:
    {
    public:
    	mere()
    	{
    		display();
    	}
     
    	virtual void display()
    	{
    		cout<<"mere::display()"<<endl;
    	}
    }
     
    class fille: public mere
    {
    public:
    	fille():mere()
    	{
    	}
     
    	void display()
    	{
    		cout<<"fille::display()"<<endl;
    	}
    }
    J'ai plusieurs filles et dans certaines la méthode display() est redéfinit.
    Cependant c'est toujours la méthode mere::display() qui est appelée.

    Une solution (lourde) serait d'appeler this->display() dans chaque constructeur fille mais n'y a-t-il pas quelquechose de plus propre ?

    merci par avance.

  2. #2
    Membre émérite 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 : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Le fonction membre appelée sera toujours celle de la classe mère.
    Lis ce tutoriel sur les fonctions virtuelles en C++.

  3. #3
    r0d
    r0d est dé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
    Effectivement. Dit autrement, la vtable n'est pas opérationnelle dans le constructeur, on ne peut donc pas utilser l'héritage de fonctions dans celui-ci.

    Une solution possible consiste à créer la classe en 2 temps, avec une fonction Create (ou Build, ou Init, ...):
    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
    struct Mere
    {
    	void Create() { Bar(); }
    	virtual void Bar() = 0;
    };
     
    struct Fille : public Mere
    {
    	void Bar() { cout << "fille" << endl; }
    };
     
    int main(int argc, char* argv[])
    {
    	Fille fille;
    	fille.Create();
     
    	return 0;
    }
    D'autres solutions sont possibles, en utilisant une factory par exemple, mais ça dépend de ce que tu veux faire exactement.

  4. #4
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 12
    Par défaut
    @Steph_ng8 merci pour le lien, ça correspond exactement à mon probleme.. malheureusement !
    @r0d en fait c'est quasiement ce que je fais à l'heure actuelle. J'ai enlevé display() du constructeur de ma classe mere et pour chaque fille je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class fille: public mere
    {
    public:
    	fille():mere()
    	{
    	}
     
    	void display()
    	{
    		mere::display();
    		//blabla...
    	}
    }
    Je trouvais cette méthode un peu lourde mais visiblement je n'ai pas trop le choix.
    Mon cas se rapproche pas mal de factory. Tu dis qu'il y a des solutions plus spécifique à ce pattern ?

    Merci par avance.

  5. #5
    r0d
    r0d est dé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
    Le problème c'est qeu ça dépend vraiment de ce que tu veux faire.
    Par exemple, si la fonction que tu veux appeler dans le constructeur ne modifie pas ta classe, alors tu peux utiliser this et ça change tout.
    Si c'est vraiment un problème de construction de la classe, ça dépend de comment sont faites des classes.
    Si c'est un problème de comportement, il faut passer par un Template Method.
    Si ce sont des classes avec sémantique de valeur, alors peut-être que la solution sera de passer par des templates.
    etc...

  6. #6
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2011
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2011
    Messages : 12
    Par défaut
    Bon ok, je vais détailler un peu alors.

    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
     
    class mere:
    {
    public:
    	mere()
    	{
    		_table = new TABLE();
    	}
     
    	virtual void display()
    	{
    		_table->Remplir();
    		_table->Afficher();
    	}
    protected:
    	TABLE* _table;
    }
     
    class fille: public mere
    {
    public:
    	fille():mere()
    	{
    		this->display();
    	}
     
    	void display()
    	{
    		//on affiche _table entièrement
    		mere::display();
     
    		//comportement particulier spécifique à fille::display()
    		_table->CacheColonne(1);
    	}
    }
    En fait ces classes servent à remplir et afficher une table provenant d'une base de donnée, ceci est fait via display(). Mes classes filles peuvent avoir un comportement plus spécifique.
    Mais dans ces cas là je suis obligé d'appeler à chaque fois display() dans le constructeur de fille.

    J'aurais pensé pouvoir le mettre dans la classe mere et avoir le bon comportement a chaque fois.

  7. #7
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 081
    Par défaut
    Une solution pour ton problème nspxroronoa, est effectivement une Factory qui se charge d'appeler les méthodes virtuelles après l'instanciation ou alors utilisé un pseudo constructeur : Qu'est-ce que l'idiome du constructeur nommé (Named Constructor) ?
    Dans les deux cas, tu finis l'initialisation de ton objet en dehors du constructeur !



    Citation Envoyé par Steph_ng8 Voir le message
    Le fonction membre appelée sera toujours celle de la classe mère.
    Lis ce tutoriel sur les fonctions virtuelles en C++.
    Sauf en C++Builder, si l'on hérite des TObject du Delphi, la VMT est chargée dès le début !

    Ainsi les méthodes virtuelles sont déjà disponible dès l'ancêtre !
    Ce qui est assez gênant car les membres objets en allocation statique sont par contre allouer normalement (au moment de chaque constructeur) mais accessible via RTTI depuis l'ancêtre !
    Du coup, on peut modifier dans un constructeur ancêtre mais on perd les données au moment du constructeur hérité ... pour un système d'objet persistant, c'est ballot !

    Si vous êtes curieux : Méthodes Virtuelles appelés depuis un Constructeur


    L'appel de méthode virtuelle dans un constructeur est même un mécanisme de base en Delphi (dont dépend tout le FrameWork de C++Builder), surtout qu'il existe aussi les constructeurs virtuelles ou même les méthodes de classes virtuelles, éléments manquants en C++Builder 2007 (et semble-t-il en C++ en général dont la philosophie est très différente de mes habitudes Delphi) : Pattern Strategy et Constructeurs Virtuels VCL
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. méthode virtuelle dans héritages
    Par bobby51 dans le forum Langage
    Réponses: 4
    Dernier message: 21/02/2010, 19h36
  2. Réponses: 6
    Dernier message: 10/10/2007, 20h11
  3. Réponses: 15
    Dernier message: 05/07/2007, 01h29
  4. Réponses: 2
    Dernier message: 10/05/2007, 17h29

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