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, Fonction virtuelle et cast


Sujet :

C++

  1. #1
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut Heritage, Fonction virtuelle et cast
    Bonjour.
    J'ai un programme contenant une classe Menu (je vous donnerais le .h en dessous) , qui contient un vecteur de Menu_Object. Tout marchait bien jusqu'à l'héritage :
    Menu me permettait d'accéder à la classe Menu_Object (via une fonction) est ainsi la fonction virtual actualise.
    Dès que j'ai commencé l'héritage en créant une classe Label, fille de Menu_Object, je me suis aperçu d'un problème :
    Puisque Menu contenait un vecteur de Menu_Object, comment accéder à la fonction actualise de mon Label puisqu'il est stocké comme un Menu_Object ?
    Existe-il une solution sans changer l'architecture ?
    Au passage, Menu_Object contient un int type supposé pouvoir m'indiquer si l'objet est un Label ou non.
    Dois-je changer mon vecteur de Menu_Object en un vecteur de void* + un vecteur de int contenant le type, puis caster quand j'appel la fonction actualise ?

    Voici mon code :

    Menu.h

    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
    #ifndef DEF_MENU
    #define DEF_MENU
     
    #include "Menu_Object.h"
    #include "Label.h"
     
    class Menu
    { 
    	private :
    		vector<Menu_Object> MyMenu;
    		vector<bool(*)(Menu&, void*, void*)> callback_functions;
    		vector<void*>fc_param;
    		void(*exit_function)(Menu&,void*);
    		void*param;
    		BITMAP*tampon;
    	public :
    		Menu(vector<Menu_Object>, void(*exit_function)(Menu&,void*)=NULL);
    		Menu(Menu_Object, void(*exit_function)(Menu&,void*)=NULL);
     
    		void add_callback_fc(bool (*)(Menu&,void*, void*), void* =NULL);
     
     
    		bool do_callback_functions();
    		void exit_fc();
     
    		void add_object(Menu_Object);
    		int get_num_objects();
    		Menu_Object& get_menu_object(int);
    		bool is_on_object(int,double, double);
    		int is_on_which_object(double,double);
     
    		void dessiner();
    };
    Menu_Object.h
    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
    44
     
    #ifndef DEF_MENU_OBJECT
    #define DEF_MENU_OBJECT
     
    #include <vector>
    using std::vector;
    #include "Rectangle.h"
     
     
     
    class Menu;
    class Menu_Object
    {
    	protected : 
    		int type;
    		bool selection;
    		int ordre;
    		bool visible;
    		vector<bool(*)(Menu&,int, void*,void*)>callback_functions;
    		vector<void*> fc_param;
    		Rectangle zone;
    		BITMAP*image_tmp;
    		bool actualiser; 
    	public :
    		Menu_Object(int,int,Rectangle&,bool=true);
     
    		int get_ordre();
    		int get_type();
    		void set_ordre(int);
    		bool get_selection();
    		void set_selection(bool);
    		bool get_visible();
    		void set_visible(bool);t
     
    		bool do_callback_functions(Menu&, int, void*);
    		void add_callback_function(bool(*)(Menu&, int, void*, void*), void* =NULL);
     
    		Rectangle& get_rectangle();
     
    		virtual void actualise();
    		void dessiner(BITMAP*);
    };
     
    #endif
    et enfin Label.h
    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
    44
     
    #ifndef DEF_LABEL
    #define DEF_LABEL
     
    #include "Menu_Object.h"
     
    #include <alfont.h>
    #define DEFAULT_FONT "comic sans ms.ttf"
    #define LABEL_TYPE 1
     
    using namespace std;
     
    class Label : public Menu_Object
    {
    	private :
    		ALFONT_FONT*police;
    		string value;
    		int col_texte; 
    		int col_fond_texte;
    		int underlined;
    	public :
    		Label(int,Rectangle&,bool=true);
    		Label(string, ALFONT_FONT*, int,Rectangle&,bool=true);
     
     
    		ALFONT_FONT* get_police(); 
    		bool set_police(char*);
    		bool set_police(string);
    		bool set_police(ALFONT_FONT*);
    		int get_col_texte();
    		bool set_col_texte(int);
    		int get_backcol_texte();
    		void set_backcol_texte(int);
    		bool delete_caract(int, int);
    		bool add_caract(char, int);
    		bool add_caract(char*, int);
    		bool add_caract(string, int);
    		int get_underlined();
    		bool set_underlined(int);
     
    		virtual void actualise();		
    };
     
    #endif

    Avez-vous des idées ? Faut-il que je reconsoive toute l'architecture du programme ? Si oui, pouvez-vous me donner une piste ?
    Merci de votre aide.

  2. #2
    zul
    zul est déconnecté
    Membre éclairé Avatar de zul
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    498
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 498
    Points : 699
    Points
    699
    Par défaut
    Comme je comprend le problème, tu n'a rien besoin de changer. L'héritage et la virtualité font exactement ce que tu attends. Le mot clé virtual indique au compilateur : "résoult l'appel de cette fonction avec le type dynamique de l'objet(Menu_object, label, ...), et pas le type statique de l'objet (Menu_object ici). Ton programme va donc appeller la bonne méthode, selon que l'objet est un Menu_object ou un Label.

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

    Informations professionnelles :
    Activité : aucun

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

    Tu devrais déjà commencer par rendre rendre le destructeurs de Menu_Objet virtuel, car il y a de fortes chances pour que tu décide de détruire la plupart des éléments de ton menu en... les faisant passer pour des objets de type Menu_Objet

    Ensuite, s'il y a bien une chose qu'il faut éviter, c'est de manipuler des pointeurs sur void.

    Par contre, tu peux parfaitement envisager d'utiliser des pointeurs sur Menu_Objet, car toutes les classes qui en dérivent de manière publique... SONT DES Menu_Objet

    Cela te permettra de profiter du comportement polymorphe actualize quel que soit le type réel (dynamique) du Menu_Objet que ton vector maintiendra

    Par contre, du seul point de vue de la sémantique, je ne suis pas sur qu'il soit réellement opportun de faire dériver laber de Menu_Objet...

    Dans "l'imaginaire populaire", un label n'est rien d'autre qu'un... rectangle dans lequel on place une chaine de caractères permettant, par exemple, de savoir ce que l'on attend que l'utilisateur introduise dans le champs qui se trouve à coté / en dessous et pouvant se placer n'importe où dans la zone utile du formulaire (mais a priori pas dans un menu ).

    De ce fait, il y a deux solutions:
    • Soit tu as très mal choisi le nom pour la classe Label, et ce devrait plutôt être Menu_Label pour clairement exprimer le fait que c'est un label destiné... à un menu
    • Soit tu veux effectivement donner le sens que je viens d'exprimer à ta classe Label, et elle peut dériver d'un tas de choses, mais pas d'un Menu_Objet, dont l'usage est, au vu du nom, ... limité aux menus


    Enfin, les menus peuvent parfaitement contenir... des sous menus.

    L'idéal est donc très souvent d'appliquer le pattern composite, étant donné qu'un menu est susceptible d'être... un élément de menu et que la seule différence entre un menu et les autres éléments de menu c'est... que le menu peut contenir des éléments (qui peuvent être des menus)

    Au final, cela nous donnerait quelque chose proche de:
    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
    /*une classe de base présentant l'interface commune */
    class Menu_Element
    {
        /* tout ce qui va bien pour cette classe */
        public:
            virtual ~Menu_Element(); /* pour pouvoir profiter du comportement
                                      * polymorphe du destructeur
                                      */
    };
    /* un menu est un Menu_Element qui peut contenir des éléments */
    class Menu : public Menu_Element
    {
        public:
            /* n'oublie pas de redéfinir les comportements polymorphes :D */
            virtual ~Menu()
            {
                /* il faut, au minimum, veiller à libérer la mémoire allouée aux 
                 * enfants
                 */
               for(std::vector<Menu_Element *>::iterator it=children_.begin();
                   it!=children_.end();++it)
                   delete (*it);
            }
        private:
            std::vector<Menu_Element* > children_; // les éléments "enfants"
    };
    /* et les éléments qui n'ont pas d'enfant */
    class Menu_Item : public Menu_Element
    {
     
        public:
            /* n'oublie pas de redéfinir les comportements polymorphes :D */
    };
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Mon objectif est de tout "controler" à l'aide de la classe Menu, or, comment je lui dis " if Mon_menu.get_menu_object(i) is Label
    alors tu execute actualise de Label.
    Si Mon_menu.get_menu_object(i) n'a pas de type alors tu execute actualise par défaut.

    Plus tard il y aura textbox et ...
    Donc il faut une méthode pour reconnaitre le type (le int type) mais ensuite il faut pouvoir appeler actualise pour le type considérer : Je n'est plus de Label dans ma classe Menu : il ne me reste que des Menu_Object. Comment faire pour a partir du int type retrouver l'objet de type Label un cast?

  5. #5
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    J'ai donc mal choisi mon nom pour Label :
    Pour moi tout les objets de mon menu sont une image (rectangulaire) avec des fonctions associées.
    Un Label (dans mon cas) est une image contenant du texte qui possède aucune fonction prédéfinie (mais rien n'empeche à l'utilisateur de faire de mon Label un bouton : il lui suffira de rajouter un pointeur de fonction et le tour est joué).

    Cependant, il est vrai que mon Menu devrait pouvoir inclure des sous-menu (je vais y penser).

    Toutefois il me semble que tu ne ma pas répondu à mon problème de base : Comment appeler depuis une classe Menu la fonction actualise de Label ?

    Pour les destructeurs, je vais bien sur faire une virtual mais je m'occupe toujours du destructeur en dernier (d'aord sa marche puis on règle les fuites mémoires...)

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Si tu définis une fonction virtuelle dans une classe, et que tu manipules une instance (un objet du type de la classe) au travers d'un pointeur ou d'une référence, ce sera automatiquement la "version" de la fonction correspondant au type réel de l'objet: c'est ca, le polymorphisme

    Tu dois manipuler ton objet au travers d'un pointeur ou d'une référence, parce que c'est le seul cas dans lequel le "type dynamique" et le "type statique" de l'objet sont potentiellement différents.

    Mais cela implique que, si tu remplis un tableau avec références ou des pointeurs sur des objets qui "passent pour être" du type de la classe de base, tu n'a même pas besoin de commencer à t'inquiéter de savoir si l'objet associé à la référence ou au pointeur est du type label, button ou machinchose et que tu peux appeler la fonction polymorphe sans te poser de question, en étant sur que ce sera la bonne "version" de celle ci qui sera appelée

    Tu trouveras une quantité d'informations (et d'explications plus détaillées) sur ce principe sur les pages de la FAQ dédiée aux fonctions virtuelles et sur celle dédiée à l'héritage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Pour les destructeurs, je vais bien sur faire une virtual mais je m'occupe toujours du destructeur en dernier (d'aord sa marche puis on règle les fuites mémoires...)
    Là, je ne suis pas d'accord...

    Quand on décide de créer une classe, il faut d'abord et avant tout:
    • Assurer une initialisation correcte et cohérente
    • S'assurer que la copie et l'affectation s'effectuent de manière cohérente s'il échoit (ou s'assurer que nous aurons une erreur le plus tôt possible si on essaye de les utiliser alors que la classe n'a pas vocation à être copiée)
    • assurer une libération cohérente des ressources manipulées par la classe.
    Quand on construit une maison, on commence par les fondations, et non par le toit (que l'on ne pourrait de toutes façons monter nulle part, tant que les murs n'existent pas).

    Les fondations d'une classe sont ses comportements fondamentaux, c'est à dire la construction, la destruction, la copie et l'assignation

    Si tu n'a pas de bases saine pour ta classe, tu ne pourra pas les tester de manière efficace et cohérente, et tu ne pourra donc pas dire que ton programme est exempt d'erreur étant donné que tu n'a pas été en mesure d'apporter la preuve qu'il en avait.

    Or, le meilleur moyen de s'assurer qu'un programme est exempt d'erreur (et surtot d'avoir la certitude qu'il sera facile d'y remédier si on en trouve) est... de tout tester le plus tôt possible: une erreur étant toujours plus facile à corriger quand on la remarque alors que le code qui la provoque est encore "tout chaud", que quand on la remarque cinq mois et 50 000 lignes de code après en avoir écrit le code.

    Ne serait-ce que parce qu'il devient très difficile de déterminer où se situe une erreur lorsque tu en arrive à une situation dans laquelle elle survient suite à des appels en cascade
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Merci de ta réponse koala. Malhereusement, la fonction actualise est appelée depuis une fonction de Menu_Object. Est-ce pour sa que c'est la fonction de Menu_Object qui est appelée ? Je te donne le code :

    La fonction du dessin du Menu, celle-ci ne gère pas encore l'ordre mais sa viendra.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void Menu::dessiner()
    {
    	int compt;
    	for(compt=0;compt<MyMenu.size();compt++)
    		MyMenu[compt].dessiner(tampon);
    	draw_sprite(screen, tampon, 0,0);
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void Menu_Object::dessiner(BITMAP*tampon)
    {
     
    	if(actualiser==false)
    		actualise();
    	draw_sprite(tampon,image_tmp, zone.get_pos().x1,zone.get_pos().y1);
    }
    La fonction d'actualise n'est pas encore finie mais ce n'est pas ce qu'il y a dedans qui importe tant.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Menu_Object::actualise()
    {
    	if(zone.get_bitmap_de_fond()==NULL)
    		clear_to_color(image_tmp,zone.get_col_fond());
    	actualiser=true;
    }
    Il ne rentre jamais dans cette fonction quand mon_menu.dessiner() est appelée (j'ai vérifié auparavant que actualiser étant bien égal à false).

    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
    void Label::actualise()
    {
    	if(police==NULL)
    		allegro_message("pb_police");
    	else
    		allegro_message("p=true");
    	int size_police=zone.get_pos().y2-zone.get_pos().y1;
    	alfont_set_font_size(police,size_police);
    	BITMAP*tampon=create_bitmap(alfont_text_length(police, value.c_str()),size_police);
    	clear_to_color(tampon, zone.get_col_fond());
    	alfont_textprintf_aa_ex(tampon, police, 0,0, col_texte, col_fond_texte, "%s", value.c_str());
    	if(tampon->w>image_tmp->w)
    		stretch_blit(tampon, image_tmp, 0,0,tampon->w, tampon->h,0,0,image_tmp->w, image_tmp->h);
    	else
    		stretch_blit(tampon, image_tmp, 0,0,tampon->w, tampon->h,(image_tmp->w-tampon->w)/2,0,image_tmp->w-(image_tmp->w-tampon->w)/2, image_tmp->h);
    	destroy_bitmap(tampon);
    	actualiser=true;
    }
    Si tu a une idée... this->actualise marcherait mieux ? this est un pointeur après tout, je serait donc en type dynamique ?
    Après essai cela ne fonctionne toujours pas.

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    Je n'ai pas tout lu les discussions sur le design. Je répond donc directement à ta question de départ.
    La mécanique des fonctions virtuelles s'applique pour les références et les pointeurs. Ton vecteur stocke les éléments par valeur. Par conséquent, lorsque tu mets un objet dans ton vecteur, tu le 'réduit' au type de base.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #ifndef DEF_MENU
    #define DEF_MENU
     
    #include "Menu_Object.h"
    #include "Label.h"
    #include <boost/shared_ptr.hpp>
    class Menu
    { 
    	private :
    		vector<boost::shared_ptr<Menu_Object> > MyMenu; // utilisation du pointeur intelligent de boost.
    Cf Les fonctions virtuelles en C++

    Comme tu t'en rends compte, souvent, l'héritage s'articule mal avec la copie. C'est pourquoi rendre ta classe non copiable permettra sans doute d'identifier plus vite ce genre de problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Menu_Object
    {
       private : 
       Menu_Object(Menu_Object const&); // ne pas définir !
       Menu_Object&operator=(Menu_Object const&); // ne pas définir !
    Je te conseille vivement de faire cela et regarder partout où tu as une erreur de compilation. Ce sont peut être des sources de problèmes, en tout cas, ce sont certainement des lignes à bien examiner et comprendre.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Non, c'est parce que tu appelle la fonction dessiner depuis un objet de type Menu_Objet et non depuis une référence ou un pointeur sur ton Menu_Objet.

    Si tu écris un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Menu_Objet mobj;
    mobj.dessiner();
    il est tout à fait normal que ce soit la version de Menu_Objet de actualise qui soit appelée, parce que le type dynamique et le type statique de ta variable sont... Menu_Objet.

    Si par contre, tu travailles avec un pointeur dans un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    // un Label qui se fait passer pour un Menu_Objet
    Menu_Objet * ptr=new Label; 
    ptr->dessiner();
    tu dispose d'une label qui "passe pour être"... un Menu_Objet.

    Lorsque actualise sera invoquée, il y aura donc résolution du type dynamique, et ce sera la version de Label qui sera appelée

    De même, si tu écris une fonction prenant une référence sur Menu_Objet proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void foo(Menu_Objet & ref)
    {
        ref.dessiner();
    }
    tu pourra avoir une résolution du type dynamique qui fera que, si c'est bel et bien un objet de type Menu_Objet, ce sera la version Menu_Objet de actualise() qui sera appelée, et que, si par contre, c'est un objet "qui passe pour être" un Menu_Objet (un label ou une classe dérivée), ce sera bel et bien la version adaptée de actualise qui sera appelée
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    J'ai donc changé mon vecteur de Menu_Object en vecteur de Menu_Objects&.
    Si j'ai bien compris je reste en type dynamique. Malheuresement quand j'appelle
    MyMenu[compt].dessiner() je perds le type dynamique ? et donc quand j'appelle actualise je suis en statique ?

    En tout cas c'est toujours dessiner de Menu_Object qui s'execute.

    3DArchi, Mozilla ne trouve pas le lien sur les fonctions virtuelles est-ce normal ?

    Si quelqu'un pouvait m'expliquer ou je perds mon type dynamique...

  12. #12
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    3DArchi, Mozilla ne trouve pas le lien sur les fonctions virtuelles est-ce normal ?
    Erreur dans le copier/coller. J'ai mis à jour le message : Les fonctions virtuelles en C++

    Citation Envoyé par NoIdea Voir le message
    J'ai donc changé mon vecteur de Menu_Object en vecteur de Menu_Objects&.
    Un vecteur de référence ??? Je demande à voir.

    Citation Envoyé par NoIdea Voir le message
    Si quelqu'un pouvait m'expliquer ou je perds mon type dynamique...
    probablement dans une copie. Rends ta classe de base non copiable pour voir où tu as une copie dans ton dos :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Menu_Object
    {
       private : 
       Menu_Object(Menu_Object const&); // ne pas définir !
       Menu_Object&operator=(Menu_Object); // ne pas définir !

  13. #13
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    J'ai ajouté les 2 lignes de code que tu m'a donné, j'ai aucun changement : tout compile patreil et s'éxécute pareil.
    En réalité je me demande si dessiner() ne devrait pas etre virtual c'est peut etre sa l'erreur.... Non, sa ne change rien

  14. #14
    Membre actif

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

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Bon j'ai finalement trouvé un moyen en mettant MyMenu comme vecteur de pointeur malheuresement sa pose d'autres problèmes... mais c'est pas grave : sa se résout. Merci pour votre aide.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/03/2006, 19h29
  2. Compilation avec des fonctions virtuel pure
    Par vanitom dans le forum C++
    Réponses: 4
    Dernier message: 16/12/2005, 14h37
  3. masquage de fonction virtuelle
    Par julien.sagnard dans le forum C++
    Réponses: 3
    Dernier message: 27/01/2005, 14h00
  4. Réponses: 2
    Dernier message: 07/10/2004, 17h00
  5. fonctions virtuelles
    Par Mau dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 21/11/2003, 09h53

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