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 especificarDestinationType
y SourceType. La implementación genérica de esta plantilla no contiene código de inicialización ni destrucción y usamemcpy
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 aAddRef
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