Partager via


Classes de stratégies de copie ATL

Les classes de stratégie de copie sont des classes utilitaires utilisées pour initialiser, copier et supprimer des données. Les classes de stratégie de copie vous permettent de définir la sémantique de copie pour n’importe quel type de données et de définir des conversions entre différents types de données.

ATL utilise des classes de stratégie de copie dans ses implémentations des modèles suivants :

En encapsulant les informations nécessaires pour copier ou convertir des données dans une classe de stratégie de copie qui peuvent être passées en tant qu’argument de modèle, les développeurs ATL ont permis un potentiel de réutilisation extrême de ces classes. Par exemple, si vous devez implémenter une collection à l’aide d’un type de données arbitraire, il vous suffit de fournir la stratégie de copie appropriée ; vous n’avez pas besoin de toucher au code qui implémente la collection.

Définition

Par définition, une classe qui fournit les fonctions statiques suivantes est une classe de stratégie de copie :

static void init( DestinationType * p);

static HRESULT copy( DestinationType * pTo, const SourceType * pFrom);

static void destroy( DestinationType * p);

Vous pouvez remplacer les types DestinationType et SourceType par des types de données arbitraires pour chaque stratégie de copie.

Remarque

Bien que vous puissiez définir des classes de stratégie de copie pour tous les types de données arbitraires, l’utilisation des classes dans le code ATL doit limiter les types qui sont logiques. Par exemple, lors de l’utilisation d’une classe de stratégie de copie avec les implémentations de collection ou d’énumérateur ATL, DestinationType doit être un type pouvant être utilisé comme paramètre dans une méthode d’interface COM.

Utilisez init pour initialiser des données, copier pour copier des données et détruire pour libérer les données. La signification précise de l’initialisation, de la copie et de la destruction est le domaine de la classe de stratégie de copie et varie en fonction des types de données impliqués.

Il existe deux exigences relatives à l’utilisation et à l’implémentation d’une classe de stratégie de copie :

  • Le premier paramètre à copier ne doit recevoir qu’un pointeur vers les données que vous avez précédemment initialisées à l’aide d’init.

  • détruire ne doit recevoir qu’un pointeur vers des données que vous avez précédemment initialisées à l’aide d’init ou copiées via copier.

Implémentations standard

ATL fournit deux classes de stratégie de copie sous la forme des classes de modèle _Copy et _CopyInterface :

  • La classe _Copy autorise uniquement la copie homogène (et non la conversion entre les types de données), car elle offre uniquement un seul paramètre de modèle pour spécifier à la fois DestinationType et SourceType. L’implémentation générique de ce modèle ne contient aucun code d’initialisation ou de destruction et utilise memcpy pour copier les données. ATL fournit également des spécialisations de _Copy pour les types de données VARIANT, LPOLESTR, OLEVERB et CONNECTDATA.

  • La classe _CopyInterface fournit une implémentation pour copier des pointeurs d’interface en suivant les règles COM standard. Une fois de plus, cette classe autorise uniquement la copie homogène, de sorte qu’elle utilise une affectation simple et un appel à AddRef pour effectuer la copie.

Implémentations personnalisées

En règle générale, vous devrez définir vos propres classes de stratégie de copie pour la copie hétérogène (autrement dit, la conversion entre les types de données). Pour obtenir des exemples de classes de stratégie de copie personnalisées, examinez les fichiers VCUE_Copy.h et VCUE_CopyString.h dans l’exemple ATLCollections. Ces fichiers contiennent deux classes de stratégie de copie de modèle, GenericCopy et MapCopy, ainsi qu’un certain nombre de spécialisations de GenericCopy pour différents types de données.

GenericCopy

GenericCopy vous permet de spécifier les SourceType et DestinationType en tant qu’arguments de modèle. Voici la forme la plus générale de la classe GenericCopy de VCUE_Copy.h :

template <class DestinationType, class SourceType = DestinationType>
class GenericCopy
{
public :
   typedef DestinationType destination_type;
   typedef SourceType      source_type;

   static void init(destination_type* p)
   {
      _Copy<destination_type>::init(p);
   }
   static void destroy(destination_type* p)
   {
      _Copy<destination_type>::destroy(p);
   }
   static HRESULT copy(destination_type* pTo, const source_type* pFrom)
   {
      return _Copy<destination_type>::copy(pTo, const_cast<source_type*>(pFrom));
   }

}; // class GenericCopy

VCUE_Copy.h contient également les spécialisations suivantes de cette classe : GenericCopy<BSTR>, GenericCopy<VARIANT, BSTR>, GenericCopy<BSTR, VARIANT>. VCUE_CopyString.h contient des spécialisations pour la copie à partir de std ::strings : GenericCopy<std::string>, GenericCopy<VARIANT, std::string>et GenericCopy<BSTR, std::string>. Vous pouvez améliorer GenericCopy en fournissant vos propres spécialisations.

MapCopy

MapCopy suppose que les données copiées sont stockées dans une carte de style bibliothèque standard C++, ce qui vous permet de spécifier le type de carte dans lequel les données sont stockées et le type de destination. L’implémentation de la classe utilise simplement les typesdefs fournis par la classe MapType pour déterminer le type des données sources et appeler la classe GenericCopy appropriée. Aucune spécialisation de cette classe n’est nécessaire.

template <class MapType, class DestinationType = MapType::mapped_type>
class MapCopy
{
public :
   typedef DestinationType               destination_type;
   typedef typename MapType::value_type  source_type;
   
   typedef MapType                       map_type;
   typedef typename MapType::mapped_type pseudosource_type;

   static void init(destination_type* p)
   {
      GenericCopy<destination_type, pseudosource_type>::init(p);
   }
   static void destroy(destination_type* p)
   {
      GenericCopy<destination_type, pseudosource_type>::destroy(p);
   }
   static HRESULT copy(destination_type* pTo, const source_type* pFrom)
   {
      return GenericCopy<destination_type, pseudosource_type>::copy(pTo, &(pFrom->second));
   }

}; // class MapCopy

Voir aussi

Implémentation d’une collection basée sur la bibliothèque standard C++
Échantillon ATLCollections