Como fazer uma coleção fortemente tipada
Este artigo explica como criar coleções fortemente tipadas para seus tipos de dados. Os tópicos incluem:
A biblioteca Microsoft Foundation Class fornece coleções fortemente tipadas predefinidas com base em modelos C++. Como são modelos, essas classes ajudam a fornecer segurança de tipos e facilidade de uso sem a conversão de tipos e outro trabalho extra envolvido no uso de uma classe sem modelo para essa finalidade. O exemplo COLLECT do MFC demonstra o uso de classes de coleção baseadas em modelo em um aplicativo MFC. Em geral, use essas classes sempre que você escrever um novo código de coleções.
Como usar classes baseadas em modelo para segurança de tipos
Para usar classes baseadas em modelo
Declare uma variável do tipo de classe de coleção. Por exemplo:
CList<int, int> m_intList;
Chame as funções de membro do objeto de coleção. Por exemplo:
m_intList.AddTail(100); m_intList.RemoveAll();
Se necessário, implemente as funções auxiliares e SerializeElements. Para informações sobre como implementar essas funções, confira Como implementar funções auxiliares.
Este exemplo mostra a declaração de uma lista de inteiros. O primeiro parâmetro na etapa 1 é o tipo de dados armazenados como elementos da lista. O segundo parâmetro especifica como os dados devem ser passados e retornados de funções membro da classe de coleção, como Add
e GetAt
.
Como implementar funções auxiliares
As classes de coleção baseadas em modelo CArray
, CList
e CMap
usam cinco funções auxiliares globais que podem ser personalizadas conforme necessário para sua classe de coleção derivada. Para informações sobre essas funções auxiliares, confira Auxiliares de Classe de Coleção na Referência do MFC. A implementação da função de serialização é necessária para a maioria dos usos das classes de coleção baseadas em modelo.
Como serializar elementos
As CArray
, CList
e CMap
chamam SerializeElements
para armazenar elementos de coleção para lê-los de um arquivo morto.
A implementação padrão da função auxiliar SerializeElements
faz uma gravação bit a bit dos objetos para o arquivo morto ou uma leitura bit a bit do arquivo morto para os objetos, dependendo se os objetos estão sendo armazenados ou recuperados do arquivo morto. Substitua SerializeElements
se essa ação não for apropriada.
Se sua coleção armazenar objetos derivados de CObject
e você usar a macro IMPLEMENT_SERIAL
na implementação da classe de elemento de coleção, poderá aproveitar a funcionalidade de serialização interna CArchive
e CObject
:
CArray< CPerson, CPerson& > personArray;
template <> void AFXAPI SerializeElements <CPerson>(CArchive& ar,
CPerson* pNewPersons, INT_PTR nCount)
{
for (int i = 0; i < nCount; i++, pNewPersons++)
{
// Serialize each CPerson object
pNewPersons->Serialize(ar);
}
}
Os operadores de inserção sobrecarregados para CArchive
chamam CObject::Serialize
(ou uma substituição dessa função) para cada objeto CPerson
.
Como usar classes de coleção sem modelo
O MFC também dá suporte às classes de coleção lançadas com o MFC versão 1.0. Essas classes não são baseadas em modelos. Elas podem ser usadas para conter dados dos tipos CObject*
, UINT
, DWORD
e CString
com suporte. Você pode usar essas coleções predefinidas (como CObList
) para armazenar coleções de todos os objetos derivados de CObject
. O MFC também fornece outras coleções predefinidas para conter tipos primitivos, como UINT
e ponteiros nulos (void*
). Porém, costuma ser útil definir suas coleções fortemente tipadas para armazenar objetos de uma classe mais específica e seus derivados. Observe que fazer isso com as classes de coleção não baseadas em modelos é mais trabalhoso do que usar as classes baseadas em modelo.
Há duas maneiras de criar coleções fortemente tipadas com as coleções sem modelo:
Use as coleções sem modelo, com conversão de tipo, se necessário. Essa é a abordagem mais fácil.
Derive e estenda uma coleção fortemente tipada sem modelo.
Para usar as coleções sem modelo com conversão de tipo
Use uma das classes sem modelo, como
CWordArray
, diretamente.Por exemplo, você pode criar uma
CWordArray
e adicionar valores de 32 bits a ela, então recuperá-los. Não há mais nada a fazer. Basta usar a funcionalidade predefinida.Você também pode usar uma coleção predefinida, como
CObList
, para manter todos os objetos derivados deCObject
. Uma coleçãoCObList
é definida para manter ponteiros paraCObject
. Ao recuperar um objeto da lista, talvez seja necessário converter o resultado no tipo adequado, já que as funçõesCObList
retornam ponteiros paraCObject
. Por exemplo, se você armazenar objetosCPerson
em uma coleçãoCObList
, precisará converter um elemento recuperado para ser um ponteiro para um objetoCPerson
. O seguinte exemplo usa uma coleçãoCObList
para armazenar objetosCPerson
:CPerson* p1 = new CPerson(); CObList myList; myList.AddHead(p1); // No cast needed CPerson* p2 = (CPerson*)myList.GetHead();
Essa técnica de usar um tipo de coleção predefinido e converter conforme necessário pode ser adequada para muitas das suas necessidades de coleção. Se você precisar de mais funcionalidade ou mais segurança de tipos, use uma classe baseada em modelo ou siga o próximo procedimento.
Para derivar e estender uma coleção fortemente tipada sem modelo
Derive sua classe de coleção de uma das classes sem modelo predefinidas.
Ao derivar sua classe, você pode adicionar funções de wrapper fortemente tipadas para fornecer uma interface fortemente tipada às funções existentes.
Por exemplo, se você tiver derivado uma lista de
CObList
para conter objetosCPerson
, poderá adicionar as funções de wrapperAddHeadPerson
eGetHeadPerson
, conforme mostrado abaixo.class CPersonList : public CObList { public: void AddHeadPerson(CPerson* person) { AddHead(person); } const CPerson* GetHeadPerson() { return (CPerson*)GetHead(); } };
Essas funções de wrapper oferecem um modo fortemente tipado para adicionar e recuperar objetos
CPerson
da lista derivada. Você pode ver que, para a funçãoGetHeadPerson
, você está simplesmente encapsulando a conversão de tipo.Você também pode adicionar funcionalidades definindo novas funções que estendem os recursos da coleção, em vez de apenas encapsular a funcionalidade em wrappers fortemente tipados. Por exemplo, o artigo Como excluir todos os objetos em uma coleção CObject descreve uma função para excluir todos os objetos contidos em uma lista. Essa função pode ser adicionada à classe derivada como uma função de membro.