Serialisierung: Erstellen einer serialisierbaren Klasse
Es sind fünf Standard Schritte erforderlich, um eine Klasse serialisierbar zu machen. Sie werden unten aufgeführt und in den folgenden Abschnitten erläutert:
Ableiten der Klasse von CObject (oder von einer klasse abgeleitet von
CObject
).Überschreiben der Memberfunktion serialisieren.
Verwenden des DECLARE_SERIAL Makros in der Klassendeklaration.
Definieren eines Konstruktors, der keine Argumente akzeptiert.
Verwenden des IMPLEMENT_SERIAL-Makros in der Implementierungsdatei für Ihre Klasse.
Wenn Sie direkt und nicht über die >> Operatoren << von CArchive aufrufenSerialize
, sind die letzten drei Schritte nicht für die Serialisierung erforderlich.
Ableiten der Klasse von CObject
Das grundlegende Serialisierungsprotokoll und die Funktionalität werden in der CObject
Klasse definiert. Durch die Ableitung Ihrer Klasse von CObject
(oder von einer von ) abgeleiteten CObject
Klasse , wie in der folgenden Deklaration der Klasse CPerson
gezeigt , erhalten Sie Zugriff auf das Serialisierungsprotokoll und die Funktionalität von CObject
.
Überschreiben der Memberfunktion "Serialisieren"
Die Serialize
Elementfunktion, die in der CObject
Klasse definiert ist, ist dafür verantwortlich, die zum Erfassen des aktuellen Zustands eines Objekts erforderlichen Daten tatsächlich zu serialisieren. Die Serialize
Funktion weist ein CArchive
Argument auf, das zum Lesen und Schreiben der Objektdaten verwendet wird. Das CArchive-Objekt verfügt über eine Memberfunktion, die angibt, IsStoring
ob Serialize
(Daten schreiben) oder geladen werden (Lesedaten). Wenn Sie die Ergebnisse IsStoring
als Anleitung verwenden, fügen Sie entweder die Daten Des Objekts mit dem Einfügeoperator (<<) in das CArchive
Objekt ein, oder extrahieren Sie Daten mit dem Extraktionsoperator (>>).
Berücksichtigen Sie eine Klasse, die von CObject
zwei neuen Membervariablen abgeleitet ist, von Typen CString
und WORD. Das folgende Klassendeklarationsfragment zeigt die neuen Membervariablen und die Deklaration für die überschriebene Serialize
Memberfunktion:
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);
};
So überschreiben Sie die Elementfunktion serialisieren
Rufen Sie die Basisklassenversion auf
Serialize
, um sicherzustellen, dass der geerbte Teil des Objekts serialisiert ist.Fügen Sie die Elementvariablen ein, die für Ihre Klasse spezifisch sind, oder extrahieren Sie sie.
Die Einfüge- und Extraktionsoperatoren interagieren mit der Archivklasse, um die Daten zu lesen und zu schreiben. Das folgende Beispiel zeigt, wie sie für die
CPerson
oben deklarierte Klasse implementiertSerialize
werden: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; }
Sie können auch die Funktionen "CArchive::Read " und "CArchive::Write member" verwenden, um große Mengen von nicht typisierten Daten zu lesen und zu schreiben.
Verwenden des DECLARE_SERIAL-Makros
Das DECLARE_SERIAL Makro ist in der Deklaration von Klassen erforderlich, die die Serialisierung unterstützen, wie hier gezeigt:
class CPerson : public CObject
{
public:
DECLARE_SERIAL(CPerson)
Definieren eines Konstruktors ohne Argumente
MFC erfordert einen Standardkonstruktor, wenn sie Ihre Objekte neu erstellt, während sie deserialisiert werden (geladen vom Datenträger). Der Deserialisierungsprozess füllt alle Membervariablen mit den Werten aus, die zum erneuten Erstellen des Objekts erforderlich sind.
Dieser Konstruktor kann öffentlich, geschützt oder privat deklariert werden. Wenn Sie sie geschützt oder privat machen, stellen Sie sicher, dass sie nur von den Serialisierungsfunktionen verwendet wird. Der Konstruktor muss das Objekt in einen Zustand versetzen, mit dem es bei Bedarf gelöscht werden kann.
Hinweis
Wenn Sie vergessen, einen Konstruktor ohne Argumente in einer Klasse zu definieren, die die DECLARE_SERIAL und IMPLEMENT_SERIAL Makros verwendet, erhalten Sie eine Compilerwarnung "Kein Standardkonstruktor verfügbar" in der Zeile, in der das IMPLEMENT_SERIAL Makro verwendet wird.
Verwenden des IMPLEMENT_SERIAL-Makros in der Implementierungsdatei
Das IMPLEMENT_SERIAL Makro wird verwendet, um die verschiedenen Funktionen zu definieren, die erforderlich sind, wenn Sie eine serialisierbare Klasse von CObject
. Sie verwenden dieses Makro in der Implementierungsdatei (. CPP) für Ihren Kurs. Die ersten beiden Argumente für das Makro sind der Name der Klasse und der Name der unmittelbaren Basisklasse.
Das dritte Argument für dieses Makro ist eine Schemanummer. Die Schemanummer ist im Wesentlichen eine Versionsnummer für Objekte der Klasse. Verwenden Sie eine ganze Zahl, die größer oder gleich 0 für die Schemanummer ist. (Verwechseln Sie diese Schemanummer nicht mit der Datenbankterminologie.)
Der MFC-Serialisierungscode überprüft die Schemanummer beim Lesen von Objekten in den Arbeitsspeicher. Wenn die Schemanummer des Objekts auf dem Datenträger nicht mit der Schemanummer der Klasse im Arbeitsspeicher übereinstimmt, löst die Bibliothek ein CArchiveException
, hindert Das Programm daran, eine falsche Version des Objekts zu lesen.
Wenn Die Serialize
Memberfunktion mehrere Versionen lesen soll , d. h. Dateien, die mit verschiedenen Versionen der Anwendung geschrieben wurden, können Sie den Wert VERSIONABLE_SCHEMA als Argument für das IMPLEMENT_SERIAL Makro verwenden. Verwendungsinformationen und ein Beispiel finden Sie in der GetObjectSchema
Memberfunktion der Klasse CArchive
.
Das folgende Beispiel zeigt, wie Sie IMPLEMENT_SERIAL für eine Klasse verwenden, CPerson
die von CObject
:
IMPLEMENT_SERIAL(CPerson, CObject, 1)
Sobald Sie über eine serialisierbare Klasse verfügen, können Sie Objekte der Klasse serialisieren, wie im Artikel Serialisierung: Serialisieren eines Objekts beschrieben.