Partilhar via


Classes de política de cópia da ATL

As classes de política de cópia são classes de utilitário usadas para inicializar, copiar e excluir dados. As classes de política de cópia permitem que você defina a semântica de cópia para qualquer tipo de dados e defina conversões entre diferentes tipos de dados.

A ATL usa classes de política de cópia em suas implementações dos seguintes modelos:

Os desenvolvedores da ATL forneceram uma reutilização extrema dessas classes ao encapsular as informações necessárias para copiar ou converter dados em uma classe de política de cópia que pode ser passada como um argumento de modelo. Por exemplo, se você precisar implementar uma coleção usando qualquer tipo de dados arbitrário, tudo o que você precisa fornecer é a política de cópia apropriada. Você nunca precisa tocar no código que implementa a coleção.

Definição

Por definição, uma classe que fornece as seguintes funções estáticas é uma classe de política de cópia:

static void init( DestinationType * p);

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

static void destroy( DestinationType * p);

É possível substituir os tipos DestinationType e SourceType por tipos de dados arbitrários para cada política de cópia.

Observação

Embora você possa definir classes de política de cópia para quaisquer tipos de dados arbitrários, o uso das classes no código ATL deve limitar os tipos que fazem sentido. Por exemplo, ao usar uma classe de política de cópia com implementações de coleção ou enumerador da ATL, DestinationType deve ser um tipo que pode ser usado como um parâmetro em um método de interface do COM.

Use o inicializar para inicializar dados, copiar para copiar dados e destruir para liberar os dados. O significado preciso de inicialização, cópia e destruição são o domínio da classe de política de cópia e variam dependendo dos tipos de dados envolvidos.

Há dois requisitos sobre o uso e a implementação de uma classe de política de cópia:

  • O primeiro parâmetro a ser copiado deve receber apenas um ponteiro para os dados que você inicializou anteriormente usando o inicializar.

  • destruir só deve receber um ponteiro para dados que você inicializou anteriormente usando o inicializar ou copiou via cópia.

Implementações padrão

A ATL fornece duas classes de política de cópia na forma das classes de modelo _Copy e _CopyInterface:

  • A classe _Copy permite somente cópia homogênea (não conversão entre tipos de dados), pois oferece apenas um único parâmetro de modelo para especificar tanto DestinationType quanto SourceType. A implementação genérica desse modelo não contém nenhum código de inicialização ou destruição e usa memcpy para copiar os dados. A ATL também fornece especializações de _Copy para o tipos de dados VARIANT, LPOLESTR, OLEVERB e CONNECTDATA.

  • A classe _CopyInterface fornece uma implementação para copiar ponteiros de interface seguindo regras do COM padrão. Mais uma vez, essa classe permite apenas cópia homogênea, portanto, ela usa uma atribuição simples e uma chamada para AddRef executar a cópia.

Implementações personalizadas

Normalmente, você precisará definir suas próprias classes de política de cópia para cópia heterogênea (ou seja, conversão entre tipos de dados). Para alguns exemplos de classes de política de cópia personalizadas, veja os arquivos VCUE_Copy.h e VCUE_CopyString.h no exemplo ATLCollections. Esses arquivos contêm duas classes de política de cópia de modelo,GenericCopy e MapCopy, além de várias especializações de GenericCopy para tipos de dados diferentes.

GenericCopy

GenericCopy permite especificar o SourceType e DestinationType como argumentos de modelo. Aqui está a forma mais geral da classe GenericCopy do 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 também contém as seguintes especializações desta classe: GenericCopy<BSTR>, GenericCopy<VARIANT, BSTR>, GenericCopy<BSTR, VARIANT>. VCUE_CopyString.h contém especializações para cópia de std::strings: GenericCopy<std::string>, GenericCopy<VARIANT, std::string> e GenericCopy<BSTR, std::string>. Você pode aprimorar GenericCopy fornecendo mais especializações próprias.

MapCopy

MapCopy pressupõe que os dados que estão sendo copiados sejam armazenados em um mapa no estilo da Biblioteca do C++ Standard, portanto, ele permite especificar o tipo de mapa no qual os dados são armazenados e o tipo de destino. A implementação da classe usa apenas os typedefs fornecidos pela classe MapType para determinar o tipo de dados de origem e chamar a classe apropriada GenericCopy. Nenhuma especialização dessa classe é necessária.

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

Confira também

Implementando uma coleção baseada na biblioteca padrão C++
Exemplo de ATLCollections