Uzyskiwanie dostępu do wszystkich elementów członkowskich kolekcji
Klasy kolekcji tablic MFC — zarówno oparte na szablonach, jak i nie — używają indeksów w celu uzyskania dostępu do ich elementów. Klasy listy MFC i kolekcji map — zarówno oparte na szablonach, jak i nie — używają wskaźnika typu POSITION , aby opisać daną pozycję w kolekcji. Aby uzyskać dostęp do co najmniej jednego członka tych kolekcji, należy najpierw zainicjować wskaźnik położenia, a następnie wielokrotnie przekazać to położenie do kolekcji i poprosić o zwrócenie następnego elementu. Kolekcja nie jest odpowiedzialna za utrzymywanie informacji o stanie postępu iteracji. Te informacje są przechowywane w wskaźniku pozycji. Jednak biorąc pod uwagę określoną pozycję, kolekcja jest odpowiedzialna za zwrócenie następnego elementu.
Poniższe procedury pokazują, jak iterować w trzech głównych typach kolekcji dostarczanych z MFC:
Aby iterować tablicę
Użyj liczb indeksu sekwencyjnego z funkcją składową
GetAt
:CTypedPtrArray<CObArray, CPerson *> myArray; myArray.Add(new CPerson()); for (int i = 0; i < myArray.GetSize(); i++) { CPerson *thePerson = myArray.GetAt(i); thePerson->AssertValid(); }
W tym przykładzie użyto tablicy wskaźników wpisanych, która zawiera wskaźniki do
CPerson
obiektów. Tablica pochodzi z klasyCObArray
, jednej z wstępnie zdefiniowanych klas.GetAt
Zwraca wskaźnik doCPerson
obiektu. W przypadku klas kolekcji wskaźników typowanych — tablic lub list — pierwszy parametr określa klasę bazową; drugi parametr określa typ do przechowywania.Klasa
CTypedPtrArray
przeciąża również operator [ ] , aby można było użyć niestandardowej składni indeksu dolnego tablicy w celu uzyskania dostępu do elementów tablicy. Alternatywą dla instrukcji w treści powyższejfor
pętli jestCPerson *thePerson = myArray[i];
Ten operator istnieje zarówno w wersjach, jak
const
i innychconst
niż. Wersjaconst
wywoływana dlaconst
tablic może być wyświetlana tylko po prawej stronie instrukcji przypisania.
Aby iterować listę
Użyj funkcji
GetHeadPosition
składowych iGetNext
do pracy z listą:CTypedPtrList<CObList, CPerson *> myList; myList.AddHead(new CPerson()); POSITION pos = myList.GetHeadPosition(); while (pos != NULL) { CPerson *thePerson = myList.GetNext(pos); thePerson->AssertValid(); }
W tym przykładzie użyto wpisanej listy wskaźników, aby zawierać wskaźniki do
CPerson
obiektów. Deklaracja listy przypomina deklarację dla tablicy w procedurze Iteracja tablicy , ale pochodzi z klasyCObList
.GetNext
Zwraca wskaźnik doCPerson
obiektu.
Aby iterować mapę
Użyj
GetStartPosition
polecenia , aby przejść na początek mapy iGetNextAssoc
wielokrotnie pobierać następny klucz i wartość z mapy, jak pokazano w poniższym przykładzie: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 }
W tym przykładzie użyto prostego szablonu mapy (a nie kolekcji wskaźnika typizowanego), który używa
CString
kluczy i przechowuje wskaźniki doCPerson
obiektów. W przypadku korzystania z funkcji dostępu, takich jakGetNextAssoc
, klasa udostępnia wskaźniki doCPerson
obiektów. Jeśli zamiast tego używasz jednej z kolekcji map nienależących do tablicy, musisz rzutować zwróconyCObject
wskaźnik na wskaźnik naCPerson
.Uwaga
W przypadku map nontemplate kompilator wymaga odwołania do
CObject
wskaźnika w ostatnim parametrze doGetNextAssoc
. W danych wejściowych należy rzutować wskaźniki do tego typu, jak pokazano w następnym przykładzie.Rozwiązanie szablonu jest prostsze i pomaga zapewnić lepsze bezpieczeństwo typów. Kod nontemplate jest bardziej skomplikowany, jak widać tutaj:
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 ... }
Aby uzyskać więcej informacji, zobacz Usuwanie wszystkich obiektów w kolekcji CObject.