Udostępnij przez


Serializacja: tworzenie klasy z możliwością 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. Za pomocą makra DECLARE_SERIAL w deklaracji klasy.

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

  5. Użycie makra IMPLEMENT_SERIAL w pliku implementacji w przypadku twojej klasy.

Jeśli wywołasz Serialize bezpośrednio, a nie za pośrednictwem operatorów >> i << obiektu 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 (lub z klasy pochodzącej z CObject), jak pokazano w deklaracji klasy CPerson, uzyskujesz dostęp do protokołu serializacji i funkcjonalności CObject.

Nadpisywanie funkcji składowej serializacji

Funkcja członkowska Serialize, która jest zdefiniowana w klasie CObject, jest odpowiedzialna za 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ą, IsStoring, która określa, czy Serialize przechowuje (zapisuje dane) czy ładuje (odczytuje dane). Korzystając z wyników IsStoring jako przewodnika, wstawiasz dane swojego obiektu do obiektu CArchive za pomocą operatora wstawiania (<<) albo wyodrębniasz dane za pomocą operatora wyodrębniania (>>).

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

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 niesprecyzowanych 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 / Notatka

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 dziedziczenia klasy możliwej do serializacji z klasy CObject. 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, aby funkcja składowa Serialize mogła odczytywać wiele wersji — to znaczy plików zapisanych w różnych wersjach aplikacji — możesz użyć wartości VERSIONABLE_SCHEMA jako argumentu 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 także

Serializacja