Udostępnij za pośrednictwem


Serializacja: ustawianie klasy jako możliwej do serializacji

Do serializacji klasy wymagane jest pięć głównych kroków. Są one wymienione poniżej i wyjaśnione w następujących sekcjach:

  1. Wyprowadzanie klasy z obiektu CObject (lub z jakiejś klasy pochodzącej z CObjectklasy ).

  2. Zastępowanie funkcji składowej Serialize.

  3. Użycie makra DECLARE_SERIAL w deklaracji klasy.

  4. Definiowanie konstruktora, który nie przyjmuje żadnych argumentów.

  5. Za pomocą makra IMPLEMENT_SERIAL w pliku implementacji dla klasy.

Jeśli wywołasz Serialize metodę bezpośrednio, a nie za pośrednictwem >> operatorów i << CArchive, ostatnie trzy kroki nie są wymagane do serializacji.

Wyprowadzanie klasy z obiektu CObject

Podstawowy protokół serializacji i funkcjonalność są definiowane w CObject klasie . Wyprowadzając klasę z CObject klasy (lub klasy pochodzącej z CObjectklasy ), jak pokazano w poniższej deklaracji klasy CPerson, uzyskujesz dostęp do protokołu serializacji i funkcjonalności klasy CObject.

Zastępowanie funkcji składowej serializacji

Funkcja Serialize składowa, która jest zdefiniowana w CObject klasie, jest odpowiedzialna za faktycznie serializowanie danych niezbędnych do przechwycenia bieżącego stanu obiektu. Funkcja Serialize ma CArchive argument używany do odczytywania i zapisywania danych obiektu. Obiekt CArchive ma funkcję składową , która wskazuje, IsStoringczy Serialize są przechowywane (zapisywanie danych) lub ładowanie (odczytywanie danych). Korzystając z wyników IsStoring przewodnika, możesz wstawić dane obiektu do CArchive obiektu za pomocą operatora wstawiania (<<) lub wyodrębnić dane z operatorem wyodrębniania (>>).

Rozważ klasę, która pochodzi z CObject klasy i ma dwie nowe zmienne składowe, typów CString i programu WORD. Poniższy fragment deklaracji klasy przedstawia nowe zmienne składowe i deklarację dla funkcji przesłoniętej Serialize składowej:

class CPerson : public CObject
{
public:
   DECLARE_SERIAL(CPerson)
   // empty constructor is necessary
   CPerson();
   virtual ~CPerson();

   CString m_name;
   WORD   m_number;

   void Serialize(CArchive& archive);
};

Aby zastąpić funkcję składową Serialize

  1. Wywołaj wersję klasy bazowej , Serialize aby upewnić się, że dziedziczona część obiektu jest serializowana.

  2. Wstaw lub wyodrębnij zmienne składowe specyficzne dla klasy.

    Operatory wstawiania i wyodrębniania współdziałają z klasą archiwum, aby odczytywać i zapisywać dane. W poniższym przykładzie pokazano, jak zaimplementować Serialize dla klasy zadeklarowanej CPerson powyżej:

    void CPerson::Serialize(CArchive& archive)
    {
       // call base class function first
       // base class is CObject in this case
       CObject::Serialize(archive);
    
       // now do the stuff for our specific class
       if (archive.IsStoring())
          archive << m_name << m_number;
       else
          archive >> m_name >> m_number;
    }
    

Możesz również użyć funkcji składowych CArchive::Read i CArchive::Write, aby odczytywać i zapisywać duże ilości nietypowych danych.

Używanie makra DECLARE_SERIAL

Makro DECLARE_SERIAL jest wymagane w deklaracji klas, które będą obsługiwać serializacji, jak pokazano poniżej:

class CPerson : public CObject
{
public:
   DECLARE_SERIAL(CPerson)

Definiowanie konstruktora bez argumentów

MFC wymaga domyślnego konstruktora podczas ponownego tworzenia obiektów, ponieważ są one deserializowane (ładowane z dysku). Proces deserializacji wypełni wszystkie zmienne składowe wartościami wymaganymi do ponownego utworzenia obiektu.

Ten konstruktor można zadeklarować jako publiczny, chroniony lub prywatny. Jeśli ustawisz ją jako chronioną lub prywatną, upewnij się, że będzie ona używana tylko przez funkcje serializacji. Konstruktor musi umieścić obiekt w stanie, który umożliwia jego usunięcie w razie potrzeby.

Uwaga

Jeśli zapomnisz zdefiniować konstruktor bez argumentów w klasie używającej DECLARE_SERIAL i makr IMPLEMENT_SERIAL, w wierszu, w którym jest używane makro IMPLEMENT_SERIAL, otrzymasz ostrzeżenie kompilatora "brak dostępnego domyślnego konstruktora".

Używanie makra IMPLEMENT_SERIAL w pliku implementacji

Makro IMPLEMENT_SERIAL służy do definiowania różnych funkcji potrzebnych podczas tworzenia klasy możliwej do serializacji z CObjectklasy . To makro jest używane w pliku implementacji (. CPP) dla klasy. Pierwsze dwa argumenty makra to nazwa klasy i nazwa jej natychmiastowej klasy bazowej.

Trzecim argumentem tego makra jest numer schematu. Numer schematu jest zasadniczo numerem wersji dla obiektów klasy. Użyj liczby całkowitej większej lub równej 0 dla numeru schematu. (Nie należy mylić tego numeru schematu z terminologią bazy danych).

Kod serializacji MFC sprawdza numer schematu podczas odczytywania obiektów do pamięci. Jeśli numer schematu obiektu na dysku nie jest zgodny ze schematem klasy w pamięci, biblioteka zgłosi CArchiveExceptionbłąd , uniemożliwiając programowi odczytywanie nieprawidłowej wersji obiektu.

Jeśli chcesz Serialize , aby funkcja składowa mogła odczytywać wiele wersji — czyli plików zapisanych w różnych wersjach aplikacji — możesz użyć wartości VERSIONABLE_SCHEMA jako argumentu do makra IMPLEMENT_SERIAL. Aby uzyskać informacje o użyciu i przykład, zobacz GetObjectSchema funkcję składową klasy CArchive.

W poniższym przykładzie pokazano, jak używać IMPLEMENT_SERIAL dla klasy , CPersonktóra pochodzi z CObjectklasy :

IMPLEMENT_SERIAL(CPerson, CObject, 1)

Po utworzeniu klasy możliwej do serializacji można serializować obiekty klasy, zgodnie z opisem w artykule Serializacja: serializacja obiektu.

Zobacz też

Serializacja