| auteur : 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 :
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 :
void SetDatas (int nSize,double * ptableau)
{
}
DoubleArray dArray;
SetDatas (dArray.GetSize (),dArray.GetData ( ));
|
|
| auteur : Farscape | La première idée serait de faire :
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:
# 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);
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:
typedef CArrayEx< CString ,const char * > StringArray;
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)));
}
}
|
|
| auteur : Farscape |
Imaginons que je veuille écrire la chose suivante :
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:
# 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>
{
public :
CListEx (int nBlockSize = 10 );
CListEx (const CListEx & x);
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:
class Gage : public CObject
{
public :
DECLARE_SERIAL ( Gage )
Gage (){ Clear ();}
~ Gage (){ }
Gage (const Gage & rItem)
{
CopyFrom (rItem);
}
const Gage& operator = (const Gage& Src)
{
CopyFrom (Src);
return * this ;
}
void Clear ()
{
}
void CopyFrom (const Gage& Src )
{
if (this = = & Src) return ;
Clear ();
}
} ;
|
Ensuite on pourra écrire:
typedef CListEx< Gage,Gage & > ListGage;
typedef CList< ListGage,ListGage & > ListOfListGage;
|
|
| auteur : 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 :
# 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
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 );
CMapEx (const CMapEx & x);
CMapEx & operator = (const CMapEx& x);
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:
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);
}
|
|
Consultez les autres F.A.Q.
|
|