Partage
  • Partager sur Facebook
  • Partager sur Twitter

Classe Abstraite & Appel de méthode virtuelle pure

Méli-mélo virtuel :P

    14 août 2008 à 21:25:43

    Bonjour tout le monde :D ,

    Voilà, je suis comme qui dirait embêté car je n'arrive pas à réaliser ce que je voudrais !

    Alors, je vais essayer d'expliquer mon problème :
    Je dispose d'une classe abstraite Core::Abstract::Engine, qui possède deux méthodes virtuelles pures, à savoir void load() et void kill() throw().

    Je voudrais créer le constructeur et le destructeur de cette classe abstraite de manière à appeler ces méthodes virtuelles pures, qui seront, bien entendu, redéfinies dans les classes qui en hériteront, sans avoir à récrire tous les constructeurs et destructeurs des mes classes filles pour y mettre la même chose !

    Puisque, je pense, du code est plus explicite, le voici :

    namespace Core
    {
    	namespace Abstract
    	{
    		class Engine
    		{
    			public:
    				Engine()
    				{
    					this->load();
    				}
    				
    				virtual ~Engine() throw()
    				{
    					this->kill();
    				}
    
    				virtual void load() = 0;
    				virtual void kill() throw() = 0;
    		};
    	}
    }
    


    En-tête de la classe héritant de la classe abstraite (les méthodes sont implémentées ailleurs)
    namespace Audio
    {
    	class Engine: public Core::Abstract::Engine
    	{
    		public:
    			void load();
    			void kill() throw();
    	};
    }
    


    Et je voudrais donc que lorsque je fasse, grâce au polymorphisme, il y ait appel de la fonction void Audio::Engine::load(), puis à void Audio::Engine::kill() throw().

    Core::Abstract::Engine * audio = new Audio::Engine;
    
    delete audio;
    


    Seulement, j'ai un problème au linkage : ld me crie undefined reference to `Core::Abstract::Engine::kill()' (et son équivalent pour load)

    Merci d'avance pour vos lumières ^^
    • Partager sur Facebook
    • Partager sur Twitter
      14 août 2008 à 21:56:43

      Citation : Hiz0

      Seulement, j'ai un problème au linkage : ld me crie undefined reference to `Core::Abstract::Engine::kill()' (et son équivalent pour load)



      A quelle ligne ?

      Sinon à par ça, tu ne pourras pas faire ce que tu veux dans le ctor (pas comme ça), la table des liens de ta classe n'est faite qu'à la sortie du construteur.
      • Partager sur Facebook
      • Partager sur Twitter
        14 août 2008 à 22:00:49

        Bonsoir,

        Je ne m'y connais pas trop en méthodes virtuelles (je n'ai lu un cours qu'il y a une semaine dessus, de plus je me demande à quoi sert au sens large, une classe abstraite), mais d'après le cours que j'ai lu, il est mieux de mettre un constructeur au moins par classe pour éviter ce genre de problèmes ; après, les auteurs ne justifient pas plus que ça.

        D'autre part, as-tu essayé simplement de remettre les prototypes des fonctions au dessus des constructeurs et destructeurs de Engine ?? Je sais pas si ça peut poser problème à la compilation de ne pas les mettre dans le "bon sens".

        Voilà, je ne pense pas que j'aurai pu t'aider vu mon niveau, mais ce sujet m'intéresse. Bon courage pour la suite !
        • Partager sur Facebook
        • Partager sur Twitter
          14 août 2008 à 22:11:36

          Citation : Chlab_lak

          A quelle ligne ?



          La ligne d'où l'erreur provient est celle où j'implémente le constructeur (et respectivement le destructeur) de ma classe abstraite.

          Citation : Chlab_lak

          Sinon à par ça, tu ne pourras pas faire ce que tu veux dans le ctor (pas comme ça), la table des liens de ta classe n'est faite qu'à la sortie du construteur.



          Ah d'accord, donc je suis obligé de faire autrement ?
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            14 août 2008 à 22:15:58

            Citation

            Sinon à par ça, tu ne pourras pas faire ce que tu veux dans le ctor (pas comme ça), la table des liens de ta classe n'est faite qu'à la sortie du construteur.


            +1. Et plus précisément, lors d'un appel de fonction dans le constructeur/destructeur, c'est une liaison statique qui est effectuée. Dès lors, si la fonction au niveau de la classe est virtuelle pure, boom !!.

            Pour plus de détails:
            http://www.generation-nt.com/reponses/ [...] e-182248.html

            Edit: pour que ca compile, retire les appels à load et kill du constructeur/destructeur.
            Je cherche le pourquoi

            Edit2: J'ai trouvé la justification exacte pour la raison du boom en cas d'appel dynamique à une fonction virtuelle pure dans le constructeur/destructeur.

            Citation : Norme C++ (10.4)


            Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed) from such a constructor (or destructor) is undefined.



            Edit3: comme c'est un UB, un plantage au niveau du link est p-e l'implémentation que ton compilo à choisi, ce qui expliqurai que ca part si on enlève les appels des constructeur/destructeur
            • Partager sur Facebook
            • Partager sur Twitter
              15 août 2008 à 0:06:13

              Citation : Davidbrcz

              retire les appels à load et kill du constructeur/destructeur.



              Oui, c'était justement le centre de ma question :p .

              Je voulais savoir si je pouvais les appeler directement et donc apparemment non !
              • Partager sur Facebook
              • Partager sur Twitter
                15 août 2008 à 0:17:22

                A partir du moment où les fonctions sont effectivement virtuelles pures (et non juste virtuelles), tu ne peux les appeler dans le constructeur/destructeur.

                Si elles sont simplement virtuelles, tu peux le faire et tu peux notamment mettre en place l'idiome du constructeur virtuel (lmghs a déjà du en parler ici ;)). Ca consiste à appeler dans le constructeur de la mère une méthode virtuelle de la mère. Quand tu la redéfiniras dans la fille cette méthode, lorsqu'une fille se construira ça appellera bien la méthode de la fille dans le constructeur et non celle de la mère. D'où le nom de "constructeur virtuel".
                • Partager sur Facebook
                • Partager sur Twitter
                  15 août 2008 à 1:36:38

                  Quoi ?
                  Dans ce que tu expliques, je comprends un truc qui est impossible.

                  Dans un constructeur (/destructeur), le type dynamique est le type statique. La fonction virtuelle appelée est toujours celle qui correspond au type dynamique. Vu le cas particulier du constructeur ... cela ne sera donc jamais celle du type enfant qui sera appelée depuis le constructeur du type parent.


                  Après, j'ai tendance à parler de post-construction polymorphique :
                  - des constructeurs protégés
                  - des fonctions virtuelles protégées concluant le boulot des constructeurs (d'où le "post")
                  - une factory (publique) qui s'occupe de construire l'objet du bon type tout en assurant que la fonction virtuelle concluant la construction soit toujours bien appelée.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                    15 août 2008 à 12:07:57

                    lmghs > je parlais du 2ème point que tu donnes en fin de ton post ;)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Classe Abstraite & Appel de méthode virtuelle pure

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown