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 :

typeid et constructeurs


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut typeid et constructeurs
    Bonjour à tous. J'ai un problème : Ce code m'affiche Base puis Derived au lieu de Derived et Derived. Comment éviter ce problème ?

    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
    #include <iostream>
    #include <typeinfo>
    using namespace std;
     
    class Base
    {
        public :
            Base(){std::cout<<"\nType="<<typeid(*this).name();}
    };
     
    class Derived : public Base
    {
        public :
            Derived() : Base()
            {
                std::cout<<"\nType="<<typeid(*this).name();
            }
    };
     
    int main()
    {
        Derived a;
        return 0;
    }
    Merci de votre aide.

  2. #2
    Membre confirmé
    Homme Profil pro
    Directeur des systèmes d'information
    Inscrit en
    Novembre 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Directeur des systèmes d'information
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2007
    Messages : 53
    Par défaut
    D'après moi ton code répond normalement.
    Ta classe Derived hérite bien de Base;

    -----------------------
    | BASE |
    -----------------------
    | Base() {}; |
    -----------------------
    |
    \ /
    -----------------------
    | DERIVED |
    -----------------------
    | Derived() {}; |
    -----------------------

    L'ordre d'appel des construteurs se fait toujours de la classe la plus générale à la plus spécialisée. De manière symétrique, les destructeurs sont appelées de la classe la plus spécialisée vers la plus générique.


    F.A.Q. :Dans quel ordre sont construits les différents composants d'une classe ?

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Je ne dis pas que c'est anormal, je me demande juste comment on peut l'évité :
    Dans Base, j'ai une fonction virtuelle. Le constructeur de Base passe en paramètre this à un autre objet.

    Le problème :

    Quand l'autre objet appelle la fonction virtuelle, c'est base qui est exécutée et non Derived. Comment éviter ce problème ?

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Dans le constructeur on évite tout ce qui est RAII/polymorphisme car il est faussé.

    Donc dans ton premier constructeur le type de ton objet est Base et non dérivé même si au final tu construit un dérivé.

    De même si tu fais quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    struct A { A() { foo(); } virtual void foo() { std::cout <<  0; } };
    struct B : A { virtual void foo() { std::cout << 1; } };
    Et que tu fais un B, la sortie sera 0 et pas 2 comme tu pourrais t'y attendre.

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Excusez-moi, mais je vais devoir débiter beaucoup de code car :
    L'exemple que j'ai pris avec Base et Derived marche impeccablement mais l'exemple réel non.

    Voici l'exemple réel (j'ai essayé de fournir que les parties utiles) :

    Le main (rien de compliqué) :

    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
    int main()
    {
        try
        {
        sf::RenderWindow w(VideoMode(800,600), "test");
        sf::GUI::Application app(w, (WindowHandle)NULL);
        Image img;
        img.LoadFromFile("ferme.jpg");
        sf::Sprite s(img);
        Button(app, Implementation::Rectangle<float>(100.f,100.f,200.f,200.f),0u,s);
        app.Wait();
        }
        catch(...)
        {
            std::cout<<"UnknownException";
        }
     
        return 0;
    }
    Le constructeur de button (button hérite de GraphicObject).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Button(sf::GUI::Application& App, Implementation::Rectangle<float> Pos, unsigned int Plane, sf::Sprite& Img) : GraphicObject(App, Pos, Plane), Image(Img)
    {
        std::cout<<"\nObjectType="<<typeid(*this).name();
        Image.SetPosition(Position.Left, Position.Top);
        Image.Resize(Pos.Right-Pos.Left,Pos.Bottom-Pos.Top);
    }
    Le constructeur de GraphicObject :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    GraphicObject::GraphicObject(sf::GUI::Application& App, Implementation::Rectangle<float>& Pos, unsigned int Plane):
        Parent(NULL), Application(App), Visible(true)
    {
        std::cout<<"\nObjectType="<<typeid(*this).name();
        //assert((App.GlPosition()).Contains(Pos));
        Position=Pos;
        ClippingEquations[0]=ClipEquation(1,0,0,Pos.Left,0);
        ClippingEquations[1]=ClipEquation(-1,0,0,Pos.Right,1);
        ClippingEquations[2]=ClipEquation(0,1,0,Pos.Top,2);
        ClippingEquations[3]=ClipEquation(0,-1,0,Pos.Bottom,3);
        App.RegisterWidget(this, Plane);
    }
    Et maintenant RegisterWidget qui est du type Sorted<GraphicObject*,unsigned int>

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    inline void sf::GUI::Application::RegisterWidget(GraphicObject*ChildWidget, unsigned int plan)
    {
        std::cout<<"\nObjectType="<<typeid(*ChildWidget).name();
        ChildWidgets.AddElement(ChildWidget, plan);
    }
    Voici le .hpp de Sorted :

    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
     
    template<typename Object, typename Sort,template<typename, typename>class Storing>
    class Sorted<Object*, Sort, Storing>
    {
        private :
            Storing<std::pair<Object*, Sort>, std::allocator<std::pair<Object*, Sort>>> List;
        public :
            Sorted()=default;
            Sorted(const Sorted&)=delete;
            Sorted& operator=(Sorted&)=delete;
            ~Sorted()=default;
            void AddElement(Object* Element, Sort Position);
            inline void EraseElement(Object* Element);
            template<typename Fc>
            inline void ForEach(Fc Function);
    };
    Et Sorted.inl :

    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
     
     
    template<typename Object, typename Sort, template<typename,typename>class Storing>
    inline void sf::GUI::Implementation::Sorted<Object*, Sort, Storing>::AddElement(Object* Element, Sort Position)
    {
        std::cout<<"\nObjectType="<<typeid(*Element).name();
        auto it=List.begin();
        for(;it!=List.end();it++)
            if(it->second<=Position)
                break;
        List.insert(it,std::make_pair(Element,Position));
    }
     
    template<typename Object, typename Sort, template<typename,typename>class Storing>
    void sf::GUI::Implementation::Sorted<Object*, Sort, Storing>::EraseElement(Object* Element)
    {
        for(auto it=List.begin();it!=List.end();it++)
        {
            if(it->first==Element)
            {
                List.erase(it);
                return ;
            }
        }
    }
     
     
    template<typename Object, typename Sort, template<typename,typename>class Storing>
    template<typename Fc>
    inline void sf::GUI::Implementation::Sorted<Object*, Sort, Storing>::ForEach(Fc Function)
    {
        for(auto it=List.begin();it!=List.end();it++)
        {
            std::cout<<"\nObjectType="<<typeid(*(it->first)).name();
            sf::GUI::Implementation::CallFunction<Fc, Object, void>::Call(Function, *(it->first));
        }
    }
    Voici le code qui appelle ForEach :

    ChildWidgets.ForEach(&GraphicObject::Actualise);

    (Ce code est appelé au début de Wait()

    Actualise appelle Draw qui est une fonction virtuelle.
    Le problème : le Draw appelé et celui de graphicObject et non de button.

    Vous risquez d'avoir besoin de cette portion de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template<typename Obj, typename R, typename ...Args>
    struct CallFunction<R(Obj::*)(Args...),Obj,R,Args...>
    {
        inline static R Call(R(Obj::*Function)(Args...), Obj& Object, Args...Arguments)
        {
            std::cout<<"\nCalling "<<typeid(Object).name();
            return (Object.*Function)(Arguments...);
        }
    };
    Merci à tous ceux qui auront déjà lut (même en diagonal) ce post.

  6. #6
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Désolé d'être un peu flemmard, mais tu pourrais pas essayer de tout réduire à un seul fichier compilable avecun copier-coller ? Ca serait bien plus simple ...

    (Je regarde quand même).

  7. #7
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Après avoir tester, l'utilisation de ton ForEach avec des élément d'une hiérarchie polymorphique et une fonction virtuelle (hors des constructeurs, dans les constructeur le polymorphisme est proscrit en général) marche comme prévue chez moi, l'erreur vient d'ailleur.
    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
     
    struct A { virtual void foo() { std::cout << 0; } virtual ~A() {} };
    struct B : A { void foo() { std::cout << 1; } };
     
    template<typename, typename, typename, typename...>
    struct CallFunction;
     
    template<typename Obj, typename R, typename ...Args>
    struct CallFunction<R(Obj::*)(Args...),Obj,R,Args...>
    {
      static R Call(R(Obj::*Function)(Args...), Obj& Object, Args...Arguments)
      { return (Object.*Function)(Arguments...); }
    };
     
    template<typename, typename, template<typename, typename> class>
    struct Sorted;
     
    template<typename Object, typename Sort,template<typename, typename>class Storing>
    class Sorted<Object*, Sort, Storing>
    {
      private :
        Storing<std::pair<Object*, Sort>, std::allocator<std::pair<Object*, Sort>>> List;
      public :
        void AddElement(Object* Element, Sort Position)
        {
          auto it=List.begin();
            for(; it != List.end(); ++it) if(it->second <= Position) break;
          List.insert(it,std::make_pair(Element,Position));
        }
        template<typename Fc> void ForEach(Fc Function)
        {
          for(auto it = List.begin(); it != List.end(); ++it)
            CallFunction<Fc, Object, void>::Call(Function, *(it->first));
        }
    };
     
    int main()
    {
      Sorted<A*, size_t, std::vector> s;
      s.AddElement(new A(), 0); s.AddElement(new B(), 1);
      s.ForEach(&A::foo);
      system("PAUSE"); return 0; 
    }

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

Discussions similaires

  1. [Reflection] Récupérer un constructeur ayant un paramètre int
    Par narmataru dans le forum API standards et tierces
    Réponses: 2
    Dernier message: 09/07/2004, 09h53
  2. [VB6]Déclaration d'un Constructeur Spécialisé
    Par TagadaTsoin dans le forum VB 6 et antérieur
    Réponses: 21
    Dernier message: 26/05/2004, 14h09
  3. [Constructeur]Pb avec la surcharge d un constructeur
    Par cmoulin dans le forum Langage
    Réponses: 3
    Dernier message: 26/04/2004, 09h29
  4. Capture d'exception dans un constructeur
    Par declencher dans le forum Composants VCL
    Réponses: 8
    Dernier message: 03/02/2004, 12h52
  5. pb constructeurs classes dérivant classe abstraite
    Par Cornell dans le forum Langage
    Réponses: 2
    Dernier message: 10/02/2003, 19h02

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