Porady: tworzenie bezpiecznej kolekcji

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 i łatwość użycia bez rzutowania typu i innych dodatkowych prac związanych z używaniem klasy nieplate 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żywanie klas opartych na szablonach dla typu Sejf ty

Aby użyć klas opartych na szablonach

  1. Zadeklaruj zmienną typu klasy kolekcji. Przykład:

    CList<int, int> m_intList;
    
  2. Wywołaj funkcje składowe obiektu kolekcji. Przykład:

    m_intList.AddTail(100);
    m_intList.RemoveAll();
    
  3. 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

Klasy CArraykolekcji oparte na szablonach , CListi CMap używają pięciu globalnych funkcji pomocnika, które można dostosować zgodnie z potrzebami dla klasy kolekcji pochodnej. Aby uzyskać informacje na temat tych funkcji pomocników, zobacz Pomocnicy klas kolekcji w dokumentacji MFC. Implementacja funkcji serializacji jest niezbędna w przypadku większości zastosowań klas kolekcji opartych na szablonach.

Serializowanie elementów

Klasy CArray, CListi CMap są wywoływane SerializeElements w celu przechowywania elementów kolekcji w celu ich odczytania z archiwum.

Domyślna implementacja funkcji pomocniczej SerializeElements wykonuje bitowe zapisy z obiektów do archiwum lub bitowo odczytane z archiwum do obiektów, w zależności od tego, czy obiekty są przechowywane w archiwum, czy pobierane z archiwum. Zastąpij SerializeElements , jeśli ta akcja nie jest odpowiednia.

Jeśli kolekcja przechowuje obiekty pochodzące z CObject i używasz IMPLEMENT_SERIAL makra we wdrożeniu klasy elementów kolekcji, możesz skorzystać z funkcji serializacji wbudowanej w CArchive program 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łania CObject::Serialize (lub zastąpienia tej funkcji) dla każdego CPerson obiektu.

Używanie klas kolekcji nontemplate

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 CObjectelementu . 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 w przypadku klas kolekcji, które nie są oparte na szablonach, więcej pracy niż w przypadku klas opartych na szablonach.

Istnieją dwa sposoby tworzenia bezpiecznych kolekcji typu za pomocą kolekcji nieplate:

  1. W razie potrzeby użyj kolekcji nieplaterowych z rzutem typu. Jest to łatwiejsze podejście.

  2. Utwórz i rozszerz niepamiętną kolekcję typów.

Aby użyć kolekcji nieplate z rzutowania typu

  1. Użyj jednej z nieplaterowych klas, takich jak CWordArray, bezpośrednio.

    Możesz na przykład utworzyć i CWordArray 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 z CObjectelementu . Kolekcja jest zdefiniowana CObList do przechowywania wskaźników na CObject. Podczas pobierania obiektu z listy może być konieczne rzutowanie wyniku do odpowiedniego typu, ponieważ CObList funkcje zwracają wskaźniki do CObject. Jeśli na przykład obiekty są przechowywane CPerson w CObList kolekcji, musisz rzutować pobrany element jako wskaźnik do CPerson obiektu. W poniższym przykładzie użyto CObList kolekcji do przechowywania CPerson obiektów:

    CPerson* p1 = new CPerson();
    CObList myList;
    
    myList.AddHead(p1);   // No cast needed
    CPerson* p2 = (CPerson*)myList.GetHead();
    

    Ta technika użycia wstępnie zdefiniowanego typu kolekcji i rzutowania w razie potrzeby może być odpowiednia dla wielu potrzeb kolekcji. 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 utworzyć i rozszerzyć kolekcję bezpieczną dla typów niepamiętnych

  1. Utwórz własną klasę kolekcji z jednej ze wstępnie zdefiniowanych klas bezplatowych.

    Po utworzeniu klasy można dodać funkcje otoki bezpieczne dla typu, aby zapewnić bezpieczny dla typów interfejs do istniejących funkcji.

    Jeśli na przykład utworzono listę z CObList do przechowywania CPerson obiektów, możesz dodać funkcje AddHeadPerson otoki i GetHeadPerson, jak pokazano poniżej.

    class CPersonList : public CObList
    {
    public:
       void AddHeadPerson(CPerson* person)
       {
          AddHead(person);
       }
    
       const CPerson* GetHeadPerson()
       {
          return (CPerson*)GetHead();
       }
    };
    

    Te funkcje otoki zapewniają bezpieczny typ sposób dodawania i pobierania CPerson obiektów z listy pochodnej. Widać, że dla GetHeadPerson funkcji po prostu hermetyzujesz rzutowanie typów.

    Możesz również dodać nowe funkcje, definiując nowe funkcje, które rozszerzają możliwości kolekcji, a nie po prostu opakowując istniejące funkcje w bezpieczne otoki typów. 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ą.

Zobacz też

Kolekcje