IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

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

SommaireLes Collections de données (4)
précédent sommaire suivant
 

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( ));

Mis à jour le 22 janvier 2007 farscape

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))); 
        } 
    }

Mis à jour le 22 janvier 2007 farscape

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;

Mis à jour le 22 janvier 2007 farscape

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); 
    }

Mis à jour le 22 janvier 2007 farscape

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 ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les 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.