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 :

Comportement bizarre du "this" avec de l'héritage


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2009
    Messages : 3
    Points : 5
    Points
    5
    Par défaut Comportement bizarre du "this" avec de l'héritage
    Bonjour,

    En faisant un petit test, j'ai eu un comportement que je n'explique pas.

    Le code suivant

    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
     
    class A {
    public:
    	int x;
    	void printA() {
    		printf("+ %p\n", this);
    	}
    };
     
    class B: public A {
    public:
    	virtual ~B() {
    	}
    	void printB() {
    		printf("+ %p\n", this);
    	}
    };
     
    void test() {
    	B b;
    	b.printA();
    	b.printB();
    }
    me retourne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    + 0022FED4
    + 0022FED0

    Si je supprime mon "virtual ~B" ou que j'ajoute un "virtual ~A" ou que je supprime mon "int x", les deux "printf" retourne un "this" avec la même valeur.

    Quelqu'un a une explication a ce comportement bizarre ? (Je pensais avoir un this toujours identique avec de l'héritage).

    nb: je compile avec gcc.

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le problème, c'est que la classe B possède une fonction virtuelle (donc une vtable), et la classe A non.

    Donc, la classe A n'a aucun pointeur de vtable, alors que la classe B doit en avoir un.

    ---> Résultat, A n'est pas le premier "membre" de B, ce qui produit un cas de décalage similaire à ceux rencontrés en cas d'héritage multiple.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    En résumé, c'est comme si tu avais ceci:
    Code C++ : 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
     class A {
    public:
    	int x;
    	void printA() {
    		printf("+ %p\n", this);
    	}
    };
     
    class __virt
    {
    public:
    	virtual ~__virt() { }
    };
     
    class B : public __virt, public A {
    public:
    	virtual ~B() {
    	}
    	void printB() {
    		printf("+ %p\n", this);
    	}
    };
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2009
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2009
    Messages : 3
    Points : 5
    Points
    5
    Par défaut
    Merci Médinoc, c'est clair.

    J'ai rencontré ce problème en voulant construire du code d'arbre n-aire (parent/children) réutilisable dans toutes situations (écrire une fois pour toute des fonctions sur arbres (find recursif, ...)).

    J'étais parti sur une conception de type:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template<class T>
    class TreeNode {
    public:
    	string name;
    private:
    	list<T> children;
    	T* parent;
            ...
    Avec une méthode "add" qui rajoute un noeud un fils en mettant "this" dans le champ "parent" du fils (pouvoir remonter dans l'arbre).

    Ainsi, si je veux du code hiérarchique, je peux hériter de TreeNode ou bien alors avoir un TreeNode en membre.

    Le coté "template" me permettait de travailler sur ma classe hiérarchique finale (et pas du TreeNode).

    Je faisais quelques tests en ce sens pour me former les idées mais ce type de conception semble risqué en c++ si la valeur de "this" peut dépendre du contexte (pb ci-dessus, héritage multiple).

    J'aime bien le c++ (par rapport a java et c#) mais il y a quand même pas mal de pièges :-(

    Je vais réflechir encore à ma conception... Il y a peut être un design pattern qui en parle...

    Merci encore.

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

Discussions similaires

  1. xsl:test .... avec comportement bizarre
    Par Blue LC dans le forum XMLRAD
    Réponses: 2
    Dernier message: 10/06/2005, 13h56

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