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:
Wyprowadzanie klasy z obiektu CObject (lub z jakiejś klasy pochodzącej z
CObject
klasy ).Zastępowanie funkcji składowej Serialize.
Użycie makra DECLARE_SERIAL w deklaracji klasy.
Definiowanie konstruktora, który nie przyjmuje żadnych argumentów.
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 CObject
klasy ), 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, IsStoring
czy 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
Wywołaj wersję klasy bazowej ,
Serialize
aby upewnić się, że dziedziczona część obiektu jest serializowana.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 zadeklarowanejCPerson
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 CObject
klasy . 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 CArchiveException
błą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 , CPerson
która pochodzi z CObject
klasy :
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.