Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym artykule wyjaśniono, jak tworzyć bezpieczne kolekcje typów dla własnych typów danych. Tematy obejmują:
Biblioteka klas programu Microsoft Foundation udostępnia wstępnie zdefiniowane kolekcje bezpieczne dla typów na podstawie szablonów języka C++. Ponieważ są to szablony, te klasy pomagają zapewnić bezpieczeństwo typów oraz łatwość użycia bez konieczności rzutowania typu i innych dodatkowych prac związanych z używaniem klasy nieszablonowej w tym celu. Przykładowy zestaw COLLECT MFC demonstruje użycie klas kolekcji opartych na szablonach w aplikacji MFC. Ogólnie rzecz biorąc, należy używać tych klas za każdym razem, gdy piszesz nowy kod kolekcji.
Użycie klas Template-Based w celu zapewnienia bezpieczeństwa typów
Aby użyć klas opartych na szablonach
Zadeklaruj zmienną typu klasy kolekcji. Przykład:
CList<int, int> m_intList;Wywołaj funkcje składowe obiektu kolekcji. Przykład:
m_intList.AddTail(100); m_intList.RemoveAll();W razie potrzeby zaimplementuj funkcje pomocnika i SerializeElements. Aby uzyskać informacje na temat implementowania tych funkcji, zobacz Implementowanie funkcji pomocnika.
W tym przykładzie pokazano deklarację listy liczb całkowitych. Pierwszy parametr w kroku 1 to typ danych przechowywanych jako elementy listy. Drugi parametr określa, w jaki sposób dane mają być przekazywane i zwracane z funkcji składowych klasy kolekcji, takich jak Add i GetAt.
Implementowanie funkcji pomocnika
Szablonowe klasy kolekcji CArray, CList i CMap używają pięciu globalnych funkcji pomocniczych, które można dostosować do potrzeb klasy kolekcji pochodnej. Aby uzyskać informacje na temat tych funkcji pomocniczych, zobacz Pomocnicy klasy kolekcji w Referencji MFC. Implementacja funkcji serializacji jest niezbędna w przypadku większości zastosowań klas kolekcji opartych na szablonach.
Serializowanie elementów
Klasy CArray, CList i CMap wywołują SerializeElements w celu przechowywania elementów kolekcji lub ich odczytu z archiwum.
Domyślna implementacja funkcji pomocniczej SerializeElements wykonuje operację bitowego zapisu z obiektów do archiwum lub bitowego odczytu z archiwum do obiektów, zależnie od tego, czy obiekty są przechowywane w archiwum, czy pobierane z niego. Zastąpij SerializeElements , jeśli ta akcja nie jest odpowiednia.
Jeśli kolekcja przechowuje obiekty pochodzące z CObject i używasz makra IMPLEMENT_SERIAL w implementacji klasy elementu kolekcji, możesz skorzystać z funkcji serializacji wbudowanej w CArchive i 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);
}
}
Przeciążone operatory wstawiania dla CArchive wywołują funkcję CObject::Serialize (lub zastąpienie tej funkcji) dla każdego obiektu CPerson.
Używanie klas kolekcji nietemplatowych
MFC obsługuje również klasy kolekcji wprowadzone w MFC w wersji 1.0. Te klasy nie są oparte na szablonach. Mogą one służyć do przechowywania danych obsługiwanych typów CObject*, , UINTDWORDi CString. Za pomocą tych wstępnie zdefiniowanych kolekcji (takich jak CObList) można przechowywać kolekcje dowolnych obiektów pochodzących z CObject. MFC udostępnia również inne wstępnie zdefiniowane kolekcje do przechowywania typów pierwotnych, takich jak UINT i wskaźniki void (void*). Ogólnie rzecz biorąc, często przydatne jest zdefiniowanie własnych kolekcji bezpiecznych pod kątem typów do przechowywania obiektów bardziej konkretnej klasy i jej pochodnych. Należy pamiętać, że używanie klas kolekcji, które nie są oparte na szablonach, wymaga więcej pracy niż korzystanie z klas opartych na szablonach.
Istnieją dwa sposoby tworzenia kolekcji bezpiecznych typowo za pomocą kolekcji nietemplatowych.
W razie potrzeby użyj kolekcji nietemplatowych z konwersją typów. Jest to łatwiejsze podejście.
Wywieść z i rozszerzyć kolekcję typów bez wzorca, bezpieczną pod względem typów.
Aby użyć kolekcji nieszablonowych z rzutowaniem typów
Użyj jednej z nieplaterowych klas, takich jak
CWordArray, bezpośrednio.Możesz na przykład utworzyć
CWordArrayi dodać do niego dowolne wartości 32-bitowe, a następnie je pobrać. Nie ma nic więcej do zrobienia. Wystarczy użyć wstępnie zdefiniowanych funkcji.Możesz również użyć wstępnie zdefiniowanej kolekcji, takiej jak
CObList, do przechowywania dowolnych obiektów pochodzących zCObject. KolekcjaCObListjest zdefiniowana do przechowywania wskaźników naCObject. Podczas pobierania obiektu z listy może być konieczne rzutowanie wyniku do odpowiedniego typu, ponieważCObListfunkcje zwracają wskaźniki doCObject. Na przykład, jeśli przechowujeszCPersonobiekty wCObListkolekcji, musisz rzutować pobrany element na wskaźnik doCPersonobiektu. W poniższym przykładzie użyto kolekcjiCObList, aby przechowywać obiektyCPerson.CPerson* p1 = new CPerson(); CObList myList; myList.AddHead(p1); // No cast needed CPerson* p2 = (CPerson*)myList.GetHead();Ta technika wykorzystania wstępnie zdefiniowanego typu kolekcji i rzutowania, gdy jest to konieczne, może być odpowiednia dla wielu potrzeb związanych z kolekcją. Jeśli potrzebujesz dalszych funkcji lub większej liczby typów bezpieczeństwa, użyj klasy opartej na szablonach lub wykonaj następną procedurę.
Aby uzyskać i rozszerzyć bezpieczną dla typów kolekcję niestemplatową
Derywuj własną klasę kolekcji z jednej ze wstępnie zdefiniowanych klas nieszablonowych.
Podczas tworzenia klasy pochodnej można dodać typowo bezpieczne funkcje opakowujące, aby zapewnić typowo bezpieczny interfejs do istniejących funkcji.
Jeśli na przykład stworzono listę z
CObListdo przechowywaniaCPersonobiektów, możesz dodać funkcje otokiAddHeadPersoniGetHeadPerson, jak pokazano poniżej.class CPersonList : public CObList { public: void AddHeadPerson(CPerson* person) { AddHead(person); } const CPerson* GetHeadPerson() { return (CPerson*)GetHead(); } };Funkcje opakowujące zapewniają bezpieczny typowo sposób na dodawanie i pobieranie
CPersonobiektów z listy dziedziczonej. Można zauważyć, że dla funkcjiGetHeadPersonpo prostu dokonujesz rzutowania typów.Możesz również dodać nową funkcjonalność, definiując nowe rozszerzenia, które zwiększają możliwości kolekcji, zamiast po prostu opakowywać istniejące funkcje w bezpieczne dla typów opakowania. Na przykład artykuł Usuwanie wszystkich obiektów w kolekcji CObject opisuje funkcję usuwania wszystkich obiektów znajdujących się na liście. Tę funkcję można dodać do klasy pochodnej jako funkcję składową.