FAQ VC++ et MFCConsultez toutes les FAQ
Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013 Ajouter une question
Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++
Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.
Sur ce, je vous souhaite une bonne lecture. Farscape
Imaginons la problématique suivante :
Je dispose d'un tableau de double à gérer dynamiquement, une solution MFC simple est d'utiliser un CArray.
On pourra écrire :
Code c++ : | Sélectionner tout |
1 2 | typedef CArray<double,double&> DoubleArray; |
Maintenant comment faire si je veux récupérer un pointeur sur le tableau de double géré par la CArray ?
En utilisant la fonction GetData() Comme suit :
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 | void SetDatas(int nSize,double * ptableau) { } DoubleArray dArray; // utilisation aprés remplissage.... SetDatas(dArray.GetSize(),dArray.GetData( )); |
La première idée serait de faire :
Code c++ : | Sélectionner tout |
1 2 | CArray<CArray<CString,const char *>,CArray<CString,const char *> > tableau; |
Malheureusement la classe CArray n'implémente pas le constructeur de copie, et ce genre code provoquera une erreur à la compilation.
Pour y remédier on devra réaliser une classe avec un constructeur de copie et l'opérateur d'affectation.
La classe template ci-dessous résout ce problème:
Code c++ : | Sélectionner tout |
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 45 46 47 48 49 | #ifndef __ARRAYEX_H__ #define __ARRAYEX_H__ #if _MSC_VER < 0x0600 #pragma warning(disable : 4786) //identifier was truncated to '255' characters in the debug information #endif #ifndef __AFXTEMPL_H__ #include <afxtempl.h> #endif template<class TYPE, class ARG_TYPE> class CArrayEx: public CArray<TYPE, ARG_TYPE> { public: CArrayEx(); CArrayEx(const CArrayEx &x); // assigment operator CArrayEx &operator = (const CArrayEx& x); }; template<class TYPE, class ARG_TYPE> inline CArrayEx<TYPE, ARG_TYPE>::CArrayEx():CArray<TYPE, ARG_TYPE>() { } template<class TYPE, class ARG_TYPE> inline CArrayEx<TYPE, ARG_TYPE>::CArrayEx(const CArrayEx &x) { *this = x; } template<class TYPE, class ARG_TYPE> inline CArrayEx<TYPE, ARG_TYPE> & CArrayEx<TYPE, ARG_TYPE>::operator = (const CArrayEx& x) { if(this!=&x) { RemoveAll(); Copy(x); } return *this; } #endif |
Exemple d'application:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | typedef CArrayEx<CString ,const char *> StringArray; // Like CStringArray !! CArrayEx<StringArray,StringArray &> ArOfstrArray; StringArray strArray; strArray.Add("coucou"); ArOfstrArray.Add(strArray); for(i=0;i<ArOfstrArray.GetSize();i++) { for(int n=0;n<ArOfstrArray[i].GetSize();n++) { TRACE("\n Array[%d][%d]=%s",i,n,static_cast<const char *>(ArOfstrArray[i].GetAt(n))); } } |
Imaginons que je veuille écrire la chose suivante :
Code c++ : | Sélectionner tout |
1 2 3 | typedef CList< Gage,Gage &> ListGage; typedef CList<ListGage,ListGage &> ListOfListGage; |
Ce code provoquera inévitablement des erreurs à la compilation,
la CList ne possède pas d'opérateur d'affectation ou de constructeur de copie, de plus il faudra s'assurer que l'objet géré par la CList dispose lui aussi d'un constructeur et d'un opérateur de copie.
Le problème peut être solutionné comme suit:
Utiliser une CList qui dispose de l'opérateur de copie:
Code c++ : | Sélectionner tout |
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #ifndef LIST_EX_H__ #define LIST_EX_H__ #ifndef __AFXTEMPL_H__ #include <afxtempl.h> #endif //////////////////////////////////////////////////////////////////////////// template< class TYPE, class ARG_TYPE> class CListEx : public CList<TYPE, ARG_TYPE> { // Construction public: CListEx (int nBlockSize = 10); CListEx (const CListEx &x); // Assigment public: CListEx &operator = (const CListEx &x); }; template< class TYPE, class ARG_TYPE> inline CListEx<TYPE,ARG_TYPE>::CListEx(int nBlockSize) : CList<TYPE,ARG_TYPE>(nBlockSize) { } template< class TYPE, class ARG_TYPE> inline CListEx<TYPE,ARG_TYPE>::CListEx(const CListEx &x) { *this = x; } template< class TYPE, class ARG_TYPE> inline CListEx<TYPE,ARG_TYPE> & CListEx<TYPE,ARG_TYPE>::operator = (const CListEx &x) { if(this != &x) { TYPE tDst; TYPE tSrc; POSITION pos; RemoveAll(); pos = x.GetHeadPosition(); while(pos != NULL) { tSrc = x.GetNext(pos); CopyElements<TYPE>(&tDst,&tSrc,1); AddTail(tDst); } } return *this; } #endif |
Ensuite rajouter l'opérateur de copie et le constructeur de copie a la classe gérée par la CList en s'appuyant sur le modèle suivant:
Code c++ : | Sélectionner tout |
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 | // la classe qui contient les données class Gage : public CObject { public: DECLARE_SERIAL( Gage ) Gage(){Clear();} //----------------------------- ~Gage(){} //----------------------------- // constructeur de copie Gage(const Gage &rItem) { CopyFrom(rItem); } //----------------------------- // operateur d'affectation const Gage& operator=(const Gage& Src) { CopyFrom(Src); return *this; } //----------------------------- // effacer les données. void Clear() { //...... } //----------------------------- // copier les données d'une source. void CopyFrom(const Gage& Src ) { if(this==&Src) return; Clear(); // clear eventuel. // copie des données ici a faire... } //.... }; |
Ensuite on pourra écrire:
Code c++ : | Sélectionner tout |
1 2 3 | typedef CListEx<Gage,Gage &> ListGage; typedef CList<ListGage,ListGage &> ListOfListGage; |
La CMap comme d'ailleurs les autres classes template CArray et Clist ne possède pas d'opérateur d'affectation ou de constructeur de copie.
Un contexte définissant une CMap de CMap ou impliquant la copie d'une CMap vers une CMap provoquera des erreurs de compilations.
Le code qui suit implémente le constructeur de copie et l'opérateur d'affectation pour la CMap :
Code c++ : | Sélectionner tout |
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #ifndef MAPEX_H__ #define MAPEX_H__ #if _MSC_VER < 0x0600 #pragma warning(disable : 4786) //identifier was truncated to '255' characters in the debug information #endif #ifndef __AFXTEMPL_H__ #include <afxtempl.h> #endif // specialisation pour une CString // extrait de CMapStringToPtr::HashKey(LPCTSTR key) const :) template<> inline UINT AFXAPI HashKey<CString> (CString strKey) { LPCSTR key = strKey; UINT nHash = 0; while (*key) { nHash = (nHash<<5) + nHash + *key++; } return nHash; } template<> inline UINT AFXAPI HashKey<CString&> (CString& strKey) { LPCSTR key = strKey; UINT nHash = 0; while (*key) { nHash = (nHash<<5) + nHash + *key++; } return nHash; } template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> class CMapEx : public CMap<KEY, ARG_KEY, VALUE, ARG_VALUE> { public: CMapEx(int nBlockSize = 10); // constructeur de copie CMapEx(const CMapEx &x); // opérateur d'affection CMapEx &operator = (const CMapEx& x); // accès a la donnée par GetAt par un index comme pour un CArray VALUE GetAt(int nIndex,KEY &rKey) const; }; template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> inline CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMapEx(int nBlockSize) :CMap<KEY, ARG_KEY, VALUE, ARG_VALUE>(nBlockSize) { } template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> inline CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::CMapEx(const CMapEx &x) { *this = x; } template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> inline CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE> & CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::operator = (const CMapEx& x) { KEY rKey; VALUE rValue; POSITION pos = x.GetStartPosition(); RemoveAll(); while(pos != NULL) { x.GetNextAssoc(pos,rKey,rValue); SetAt(rKey,rValue); } return *this; } template<class KEY, class ARG_KEY, class VALUE, class ARG_VALUE> inline VALUE CMapEx<KEY, ARG_KEY, VALUE, ARG_VALUE>::GetAt(int nIndex,KEY &rKey) const { ASSERT(nIndex >= 0 && nIndex < GetCount()); POSITION pos = GetStartPosition(); VALUE rValue; do { GetNextAssoc(pos,rKey,rValue); }while(nIndex --); return rValue; } |
Ensuite on pourra écrire:
Code c++ : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | CMapEx<CString ,CString,CString ,CString> map; CMapEx<CString ,CString,CString ,CString> map2; map.SetAt("VC-MODO1","Farscape"); map.SetAt("VC-MODO2","Nico"); map.SetAt("VC-MODO3","BigBoom"); map2=map; CString key; for(int i=0;i<map2.GetCount() ();i++) { TRACE("\n%s",(const char *)map2.GetAt(i,key)); TRACE("\n%s",(const char *)key); } |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.