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

MFC Discussion :

[VC++6] Erreur avec CArray


Sujet :

MFC

  1. #1
    Futur Membre du Club
    Profil pro
    world master
    Inscrit en
    Octobre 2004
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : world master

    Informations forums :
    Inscription : Octobre 2004
    Messages : 8
    Points : 5
    Points
    5
    Par défaut [VC++6] Erreur avec CArray
    Salut à tous.
    Je viens de faire face à une erreur que je ne comprend absolument pas, et je me demandais si certains pouvaient m'éclairer. J'ai résolu le probleme mais sans comprendre pourquoi alors ca me chagrine...
    Voici le probleme:

    En gros, j'ai 2 classe, A et B avec B qui dérive de A (A est la classe parent).

    je récupere un pointeur sur B que j'essai de stocker dans un CArray contenant des pointeurs sur A (CArray<A*, A*>). Comme B dérive de A, cela me semble logique. Or, VC6 me sort une erreur sur la ligne suivante:
    monCArray->Add(monPtSurB);

    => error C2664: 'Add' : cannot convert parameter 1 from 'class CNetMobile *' to 'class CZoneGuardedMobile *'
    Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

    Je me dit "tiens c'est bizarre", je vais ruser en castant . Je modifie l'instruction comme suis:
    monCArray->Add((A*)monPtSurB);

    => la compilation passe, mais par contre, il crashe à l'exécution.

    La solution consiste juste à lui rajouter #include "B.h". A ce moment là, l'instruction comme ecrite la 1ere fois passe sans probleme. Bizarre comme probleme et messages d'erreur, non ???

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Est-ce qu'à l'endroit où il y a cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monCArray->Add(monPtSurB);
    B n'est connu que par une déclaration anticipée ? Cela semble être le cas, puisqu'une inclusion de B.h règle le problème. Dans ce cas c'est normal : avec seulement la déclaration anticipée, le compilo ne peut pas savoir que B dérive de A, et donc faire la conversion convenablement.

  3. #3
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    le plus simple etant de faire suivre la declaration de B a la suite de A
    mais bon je suis etonné que tu rencontres ce genre d'erreur dans un cas aussi simple d'utilisation.
    il serait interressant d'avoir:
    un peu de code representatif du probleme .
    le message d'erreur .
    et au fait monCArray est initialisé correctement ?



  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    Loulou24: tu as tout à fait raison, c'est exactement cela. Donc en fait, c'est vrai qu'en reflechissant un peu, c'est sur que le compilo ne peut pas deviner que B dérive de A. Par contre, je trouve que l'erreur C2664 qu'il renvoie est un peu "déroutante".

    Farscape: ca me semble compliqué de mettre le code (meme si c'est sur que pour analyser une erreur, rien ne vaut l'original), mais basiquement, je pense avoir expliqué le probleme avec mes A et mes B. Qu'entent-tu par initialiser correctement le CArray ? Je n'ai rien fait d'autre qu'appeler le constructeur puis passer un pointeur sur le CArray créé à une fonction qui le remplit.

    Le message d'erreur lors du crash (quand je caste un B* en A* à l'ajout dans l'array, sans avoir inclut B.h) se produit lorsque j'essai d'accéder à une CString membre de A lors du parcourt de mon Carray précédemment remplit. En fait, dans la classe CString se trouve un ASSERT(m_pchData != NULL) et il se trouve que m_pchData est null...
    Les raisons sont quand meme encore un peu floues...

    Merci pour vos réponses en tout cas

    PS: j'ai oublié de préciser que je viens de changer de pseudo car je n'arrive plus à me connecter avec mon ancien

  5. #5
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    ce que je veux dire c'est que ton crash doit provenir de l'utilisation de ton CArray .
    par exemple passer en argument l'adresse d'un objet local .
    ou passer l'adresse d'un objet dynamique ,detruire cet objet et ne pas supprimer l'element correspondant dans le Carray.


  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    Généralement, ce type d'erreur vient bien de là c'est sûr, mais là... Pour supprimer le crash, il me suffit de :

    - supprimer le cast explicite en A* (donc j'ecrit "monCArray->Add(monPtSurB);" au lieu de "monCArray->Add((A*)monPtSurB);" )

    - ajouter, dans le meme fichier #include "B.h"

    Tout ca m'ammene à penser que, physiquement, je n'accede pas à de la mémoire qui aurait été libérée. En fait, je ne voit pas en quoi mes corrections m'évitent d'accéder à de la mémoire à laquelle je n'ai pas le droit d'accéder. Surtout qu'avec ces corrections, mon CString contient bien ce qu'il est sensé contenir et le programme se comporte normalement.

  7. #7
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Loulou24: tu as tout à fait raison, c'est exactement cela. Donc en fait, c'est vrai qu'en reflechissant un peu, c'est sur que le compilo ne peut pas deviner que B dérive de A
    Ben... le problème est résolu alors, non ?

    En fait, je ne voit pas en quoi mes corrections m'évitent d'accéder à de la mémoire à laquelle je n'ai pas le droit d'accéder.
    En fait l'upcast (classe fille vers classe parent) n'est pas automatique, il requiert un petit calcul sur le pointeur (en gros, ton pointeur en tant que A* n'aura pas exactement la même adresse que ton pointeur en tant que B*). Enfin je crois. De toutes les manières, il faut bien que le compilo ait connaissance de l'intégralité de la classe B pour pouvoir faire correctement la conversion.

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    hé hé !
    Oui et non en fait. Ca me chagrine de ne pas comprendre pourquoi le programme crashe quand je ne fait pas mes 2 modif (voir mon précédant post). Est-ce simplement su au compilo qui fait n'importe quoi car il ne dispose pas des bonnes infos ?

    edit: je n'avais vu que la premeire partie de ta réponse. La seconde, quand tu parle d'upcast me convient tout a fait ! C'est bon, je suis "rassuré". Merci les gars

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    Bon, vous allez penser que je suis un chieur, surout pour un probleme résolu mais...
    Je viens de faire le test suivant:

    B * b = ptSurB;
    A * a = (A *)ptSurB;
    if ( (void*)a == (void*)b )
    TRACE("toto");

    Toto m'est bien affiché donc les pointeurs sont les meme, non ?

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    Arfff! A partir du moment ou j'inclu B.h, les pointeurs deviennet différent est "toto" n'est plus affiché. Bon, si quelqu'un à des liens vers des articles détaillant tout ces problemes de pointeurs je suis preneur (si j'en trouve, je reviendrai les poster ici)

  11. #11
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Bon, si quelqu'un à des liens vers des articles détaillant tout ces problemes de pointeurs je suis preneur (si j'en trouve, je reviendrai les poster ici)
    Disons que tout ce que tu as à savoir, c'est qu'à partir du moment où tu veux upcaster tu as besoin de la définition complète de la classe, et qu'une déclaration anticipée ne suffit plus. Pour les détails internes de la conversion, je ne sais pas si ce genre de considération est décrite dans la norme.

  12. #12
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    a mon avis tu te melange les pinceaux .
    ta classe B ne doit pas heritée de A ,verifie tes headers ...
    pour ton exemple tu aurais mis 10 dedans c'etait pareil ....
    en C++ il est preferable d'utiliser static_cast qui verifie a la compilation que les pointeurs sont de meme nature .
    dans ton cas si b n'herite pas de a ,tu auras une erreur a la compilation ....

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    Me mélanger les pinceaux ?! Moi ?!!
    Non, sérieusement, B hérite bien de A
    ( class B : public autreClasse, public A {.... )
    Par contre, je vais tester de ce pas le static_cast...

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut
    Alros en fait, le dynamic_cast tout comme le static_cast ne compilent pas si je n'inclus pas B.h. Or à partir du moment ou j'inclu B.h, je n'ai pas besoin de caster quoi que ce soit car Visual voit bien que je peut stocker un B* là ou est attendu un A*.
    Mais la moralité, c'est de ne jamais faire de cast barbare: toujours utiliser les opérateurs dynamic_cast et static_cast.

    Et c'est bien car j'aurai au moins appri que 2 pointeurs sur un meme objet, selon que le pointeur est déclaré comme étant du type parent ou du type fils, ne pointent pas au meme endroit (sauf si on les caste à la barbare ).

  15. #15
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    Citation Envoyé par fmarot
    Me mélanger les pinceaux ?! Moi ?!!
    Non, sérieusement, B hérite bien de A
    ( class B : public autreClasse, public A {.... )
    Par contre, je vais tester de ce pas le static_cast...
    tu vois quand je demandais du code c'etait pas pour rien
    tu n'as jamais precisé que tu utilisais l'heritage multiple .....
    donc tu ne peut pas ranger un pointeur de B dans A d'ou le crash.


  16. #16
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    29
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 29
    Points : 34
    Points
    34
    Par défaut


    tout s'éclaire maintenant ! C'est vrai que je n'avait pas pensé que cela pouvait provenir de l'héritage multiple...
    Autant pour moi. En tout cas merci Loulou24 et Farscape

Discussions similaires

  1. Erreur Avec Interbase
    Par smokemon dans le forum Bases de données
    Réponses: 1
    Dernier message: 29/10/2004, 08h24
  2. Erreur avec procédure LockWorkStation ...
    Par simonseztech dans le forum API, COM et SDKs
    Réponses: 4
    Dernier message: 16/08/2004, 16h33
  3. [Débutant][Conception] Erreur avec une classe interne
    Par Devil Redneck dans le forum Général Java
    Réponses: 5
    Dernier message: 11/06/2004, 16h45
  4. Erreur avec les ADO
    Par megane dans le forum Bases de données
    Réponses: 7
    Dernier message: 08/03/2004, 22h37
  5. Erreur avec WM_COMMAND (BN_CLICKED)
    Par cyberlewis dans le forum Windows
    Réponses: 2
    Dernier message: 09/02/2004, 01h25

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