Acessando todos os membros de uma coleção
As classes de coleção de matriz do MFC — baseadas ou não em modelo — usam índices para acessar os respectivos elementos. As classes de coleção de mapa e lista do MFC — baseadas ou não em modelo — usam um indicador do tipo POSITION para descrever uma determinada posição dentro da coleção. Para acessar um ou mais membros dessas coleções, primeiro você inicializa o indicador de posição e, em seguida, passa repetidamente essa posição para a coleção e solicita que ela retorne o próximo elemento. A coleção não é responsável por manter informações de estado sobre o andamento da iteração. Essas informações são mantidas no indicador de posição. No entanto, dada uma posição específica, a coleção é responsável por retornar o próximo elemento.
Os seguintes procedimentos mostram como iterar nos três principais tipos de coleções fornecidos com o MFC:
Para iterar uma matriz
Use números de índice sequenciais com a função membro
GetAt
:CTypedPtrArray<CObArray, CPerson *> myArray; myArray.Add(new CPerson()); for (int i = 0; i < myArray.GetSize(); i++) { CPerson *thePerson = myArray.GetAt(i); thePerson->AssertValid(); }
Este exemplo usa uma matriz de ponteiro tipada que contém ponteiros para objetos
CPerson
. A matriz é derivada da classeCObArray
, uma das classes predefinidas que não são de modelo.GetAt
retorna um ponteiro para um objetoCPerson
. Para classes de coleção de ponteiros tipadas — matrizes ou listas —, o primeiro parâmetro especifica a classe base e o segundo especifica o tipo a ser armazenado.A classe
CTypedPtrArray
também sobrecarrega o operador [ ] para que você possa usar a sintaxe de subscrito de matriz personalizada para acessar os elementos de uma matriz. Uma alternativa à instrução no corpo do loopfor
acima éCPerson *thePerson = myArray[i];
Esse operador existe em versões
const
e nãoconst
. A versãoconst
, que é invocada para matrizesconst
, só pode aparecer no lado direito de uma instrução de atribuição.
Para iterar uma lista
Use as funções de membro
GetHeadPosition
eGetNext
para percorrer a lista:CTypedPtrList<CObList, CPerson *> myList; myList.AddHead(new CPerson()); POSITION pos = myList.GetHeadPosition(); while (pos != NULL) { CPerson *thePerson = myList.GetNext(pos); thePerson->AssertValid(); }
Este exemplo usa uma lista de ponteiros tipados para conter ponteiros para objetos
CPerson
. A declaração da lista é semelhante à da matriz no procedimento Para iterar uma matriz, mas é derivada da classeCObList
.GetNext
retorna um ponteiro para um objetoCPerson
.
Para iterar um mapa
Use
GetStartPosition
para chegar ao início do mapa eGetNextAssoc
para obter repetidamente a próxima chave e o valor do mapa, conforme mostrado no seguinte exemplo:CMap<CString, LPCTSTR, CPerson *, CPerson *> myMap; CPerson myPerson; myMap.SetAt(_T("Bill"), &myPerson); POSITION pos = myMap.GetStartPosition(); while (pos != NULL) { CPerson *pPerson; CString string; // Get key (string) and value (pPerson) myMap.GetNextAssoc(pos, string, pPerson); // Use string and pPerson }
Este exemplo usa um modelo de mapa simples (em vez de uma coleção de ponteiros tipados) que usa chaves
CString
e armazena ponteiros para objetosCPerson
. Quando você usa funções de acesso, comoGetNextAssoc
, a classe fornece ponteiros para objetosCPerson
. Se você usar uma das coleções de mapa que não são de modelo, precisará converter o ponteiroCObject
retornado em um ponteiro para umCPerson
.Observação
Para mapas que não são de modelo, o compilador requer uma referência a um ponteiro
CObject
no último parâmetro paraGetNextAssoc
. Na entrada, você precisa converter os ponteiros nesse tipo, conforme mostrado no próximo exemplo.A solução de modelo é mais simples e ajuda a fornecer melhor segurança de tipos. O código sem modelo é mais complicado, como você pode ver aqui:
CMapStringToOb myMap; // A nontemplate collection class CPerson myPerson; myMap.SetAt(_T("Bill"), &myPerson); POSITION pos = myMap.GetStartPosition(); while (pos != NULL) { CPerson *pPerson; CString string; // Gets key (string) and value (pPerson) myMap.GetNextAssoc(pos, string, (CObject *&)pPerson); ASSERT(pPerson->IsKindOf(RUNTIME_CLASS(CPerson))); // Use string and pPerson ... }
Para obter mais informações, consulte Excluindo todos os objetos em uma coleção CObject.