Compartir a través de


Clases de directiva de copia de ATL

Las clases de directiva de copia son clases de utilidad que se usan para inicializar, copiar y eliminar datos. Las clases de directiva de copia permiten definir la semántica de copia para cualquier tipo de datos, así como las conversiones entre distintos tipos de datos.

ATL usa clases de directiva de copia en sus implementaciones de las plantillas siguientes:

Al encapsular la información necesaria para copiar o convertir datos en una clase de directiva de copia que se puede pasar como argumento de plantilla, los desarrolladores de ATL han proporcionado una reutilización extrema de estas clases. Por ejemplo, si necesita implementar una colección con cualquier tipo de datos arbitrario, todo lo que debe proporcionar es la directiva de copia adecuada; nunca tiene que tocar el código que implementa la colección.

Definición

Por definición, una clase que proporciona las siguientes funciones estáticas es una clase de directiva de copia:

static void init( DestinationType * p);

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

static void destroy( DestinationType * p);

Puede reemplazar los tipos DestinationType y SourceType por tipos de datos arbitrarios para cada directiva de copia.

Nota:

Aunque puede definir clases de directiva de copia para cualquier tipo de datos arbitrario, el uso de las clases en el código de ATL debe limitar los tipos que tienen sentido. Por ejemplo, cuando se usa una clase de directiva de copia con las implementaciones de enumeradores o colecciones de ATL, DestinationType debe ser un tipo que se pueda usar como parámetro en un método de interfaz COM.

Use init para inicializar los datos, copy para copiarlos y destroy para liberarlos. El significado preciso de la inicialización, la copia y la destrucción es el dominio de la clase de directiva de copia y variará en función de los tipos de datos implicados.

Hay dos requisitos sobre el uso y la implementación de una clase de directiva de copia:

  • El primer parámetro para copy solo debe recibir un puntero a los datos inicializados previamente mediante init.

  • destroy solo debe recibir un puntero a los datos inicializados previamente mediante init o copiados a través de copy.

Implementaciones estándar

ATL proporciona dos clases de directiva de copia en forma de las clases de plantilla _Copy y _CopyInterface:

  • La clase _Copy solo permite la copia homogénea (no la conversión entre tipos de datos), ya que solo ofrece un único parámetro de plantilla para especificar DestinationType y SourceType. La implementación genérica de esta plantilla no contiene código de inicialización ni destrucción y usa memcpy para copiar los datos. ATL también proporciona especializaciones de _Copy para los tipos de datos VARIANT, LPOLESTR, OLEVERB y CONNECTDATA.

  • La clase _CopyInterface proporciona una implementación para copiar punteros de interfaz siguiendo las reglas COM estándar. Una vez más, esta clase solo permite la copia homogénea, por lo que usa una asignación simple y una llamada a AddRef para realizar la copia.

Implementaciones personalizadas

Normalmente, deberá definir sus propias clases de directiva de copia para la copia heterogénea (es decir, la conversión entre tipos de datos). Para ver algunos ejemplos de clases de directiva de copia personalizadas, examine los archivos VCUE_Copy.h y VCUE_CopyString.h en el ejemplo Colecciones de ATL. Estos archivos contienen dos clases de directiva de copia de plantilla, GenericCopy y MapCopy, además de una serie de especializaciones de GenericCopy para diferentes tipos de datos.

GenericCopy

GenericCopy permite especificar SourceType y DestinationType como argumentos de plantilla. Esta es la forma más general de la clase 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 también contiene las especializaciones siguientes de esta clase: GenericCopy<BSTR>, GenericCopy<VARIANT, BSTR>, GenericCopy<BSTR, VARIANT>. VCUE_CopyString.h contiene especializaciones para copiar desde std::strings: GenericCopy<std::string>, GenericCopy<VARIANT, std::string> y GenericCopy<BSTR, std::string>. Puede mejorar GenericCopy proporcionando más especializaciones propias.

MapCopy

MapCopy supone que los datos que se copian se almacenan en un mapa al estilo de la biblioteca estándar de C++, por lo que permite especificar el tipo de mapa en el que se almacenan los datos y el tipo de destino. La implementación de la clase simplemente usa las definiciones de tipo proporcionadas por la clase MapType para determinar el tipo de los datos de origen y llamar a la clase GenericCopy adecuada. No se necesitan especializaciones de esta clase.

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

Consulte también

Implementar una recopilación basada en la biblioteca estándar de C++
Ejemplo de ATLCollections