Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Uyarı
Microsoft Foundation Sınıfları (MFC) kitaplığına destek verilmeye devam ediliyor. Ancak artık özellik eklemeyeceğiz veya belgeleri güncelleştirmeyeceğiz.
Bu not, kalıcı C++ nesnelerini destekleyen MFC yordamlarını ve dosyada depolandığında nesne verilerinin biçimini açıklar. Bu yalnızca DECLARE_SERIAL ve IMPLEMENT_SERIAL makroları olan sınıflar için geçerlidir.
Sorun
Kalıcı veri için MFC uygulaması, bir dosyanın tek bir bitişik bölümünde birçok nesnenin verilerini depolar. nesnenin Serialize yöntemi, nesnenin verilerini sıkıştırılmış ikili biçime çevirir.
Uygulama, CArchive Sınıfı kullanılarak tüm verilerin aynı biçimde kaydedilmesini garanti eder. Bir nesneyi çevirici olarak kullanır CArchive . Bu nesne, oluşturulduğu zamandan CArchive::Close çağrısına kadar kalır. Bu yöntem programcı tarafından açıkça veya program öğesini içeren CArchivekapsamdan çıktığında yıkıcı tarafından örtük olarak çağrılabilir.
Bu not, CArchive:WriteObject üyelerinin uygulamasını açıklar. Bu işlevlerin kodunu Arcobj.cpp ve ana uygulamasını CArchive Arccore.cpp içinde bulabilirsiniz. Kullanıcı kodu ReadObject ve WriteObject öğelerini doğrudan çağırmaz. Bunun yerine, bu nesneler DECLARE_SERIAL ve IMPLEMENT_SERIAL makroları tarafından otomatik olarak oluşturulan sınıfa özgü tür güvenli ekleme ve ayıklama işleçleri tarafından kullanılır. Aşağıdaki kod, WriteObject ve ReadObject'in örtük olarak nasıl çağrıldığını gösterir.
class CMyObject : public CObject
{
DECLARE_SERIAL(CMyObject)
};
IMPLEMENT_SERIAL(CMyObj, CObject, 1)
// example usage (ar is a CArchive&)
CMyObject* pObj;
CArchive& ar;
ar <<pObj; // calls ar.WriteObject(pObj)
ar>> pObj; // calls ar.ReadObject(RUNTIME_CLASS(CObj))
Nesneleri Depoya Kaydetme (CArchive::WriteObject)
yöntemi CArchive::WriteObject , nesneyi yeniden yapılandırmak için kullanılan üst bilgi verilerini yazar. Bu veriler iki bölümden oluşur: nesnenin türü ve nesnenin durumu. Bu yöntem ayrıca, yazılan nesnenin kimliğini korumaktan da sorumludur; böylece bu nesnenin işaretçi sayısına bakılmaksızın (döngüsel işaretçiler dahil) yalnızca tek bir kopya kaydedilir.
Nesneleri kaydetme (ekleme) ve geri yükleme (ayıklama) birkaç "bildirim sabiti" gerektirir. Bunlar ikili olarak depolanan ve arşive önemli bilgiler sağlayan değerlerdir ("w" ön ekinin 16 bit miktarları gösterdiğine dikkat edin):
| Etiket | Açıklama |
|---|---|
| wNullTag | NULL nesne işaretçileri (0) için kullanılır. |
| wNewClassTag | Aşağıdaki sınıf açıklamasının bu arşiv bağlamı için yeni olduğunu gösterir (-1). |
| wOldClassTag | Okunan nesnenin sınıfının bu bağlamda görüldüğünü gösterir (0x8000). |
Nesneleri depolarken arşiv, 32 bit kalıcı tanımlayıcı (PID) ile depolanan bir nesne arasındaki eşlemeyi gösteren bir CMapPtrToPtr (m_pStoreMap) tutar. Her benzersiz nesneye ve arşiv bağlamında kaydedilen her benzersiz sınıf adına bir PID atanır. Bu PID'ler 1'den başlayarak sıralı olarak dağıtılır. Bu PID'lerin arşiv kapsamı dışında bir önemi yoktur ve özellikle de kayıt numaraları veya diğer kimlik öğeleriyle karıştırılmamalıdır.
CArchive sınıfında, PID'ler 32 bittir, ancak 0x7FFE büyük olmadığı sürece 16 bit olarak yazılır. Büyük PID'ler 0x7FFF ve ardından 32 bit PID olarak yazılır. Bu, önceki sürümlerde oluşturulan projelerle uyumluluğu korur.
Bir nesneyi arşive kaydetme isteğinde bulunulduğunda (genellikle genel ekleme işleci kullanılarak), NULL CObject işaretçisi için bir denetim yapılır. İşaretçi NULL ise, wNullTag arşiv akışına eklenir.
İşaretçi NULL değilse ve seri hale getirilebilirse (sınıf bir DECLARE_SERIAL sınıftır), kod nesnenin zaten kaydedilip kaydedilmediğini görmek için m_pStoreMap denetler. Varsa, kod bu nesneyle ilişkili 32 bit PID'yi arşiv akışına ekler.
Nesne daha önce kaydedilmediyse, dikkate alınması gereken iki olasılık vardır: nesnenin hem nesnesi hem de tam türü (yani, sınıf) bu arşiv bağlamında yenidir veya nesne zaten tam olarak görülen türdedir. Türün daha önce görülüp görülmediğini belirlemek için kod, kaydedilen nesneyle ilişkili olan nesneye eşleşen bir CRuntimeClass nesnesi için m_pStoreMap'i sorgular. Eşleşme varsa, WriteObjectOR ve bu indeksin bit düzeyindeki ile bir etiket ekler.
CRuntimeClass bu arşiv bağlamında yeniyse, WriteObject bu sınıfa yeni bir PID atar ve wNewClassTag değerinin önünde arşive ekler.
Bu sınıfın tanımlayıcısı, CRuntimeClass::Store yöntemi kullanılarak daha sonra arşive eklenir.
CRuntimeClass::Store sınıfının şema numarasını (aşağıya bakın) ve sınıfın ASCII metin adını ekler. ASCII metin adının kullanılmasının, uygulamalar arasında arşivin benzersizliğini garanti etmediğini unutmayın. Bu nedenle, bozulmayı önlemek için veri dosyalarınızı etiketlemeniz gerekir. Sınıf bilgilerinin eklenmesinden sonra arşiv, nesnesini m_pStoreMap yerleştirir ve ardından sınıfa özgü verileri eklemek için yöntemini çağırır Serialize . Çağırmadan önce nesnenin Serialize yerleştirilmesi, nesnenin birden çok kopyasının depoya kaydedilmesini önler.
İlk çağırana geri dönerken (genellikle nesne ağının kökü), CArchive::Close öğesini çağırmanız gerekir. Diğer CFile işlemlerini gerçekleştirmeyi planlıyorsanız, arşiv bozulmasını CArchive önlemek için Flush yöntemini çağırmanız gerekir.
Uyarı
Bu uygulama, arşiv bağlamı başına sabit 0x3FFFFFFE dizin sınırı uygular. Bu sayı, tek bir arşive kaydedilebilecek en fazla benzersiz nesne ve sınıf sayısını temsil eder, ancak tek bir disk dosyasının sınırsız sayıda arşiv bağlamı olabilir.
Depodan Nesne Yükleme (CArchive::ReadObject)
Nesneleri yükleme (ayıklama) yöntemi CArchive::ReadObject kullanır ve WriteObject yöntemin ters işlemidir. gibi WriteObject, ReadObject kullanıcı kodu tarafından doğrudan çağrılmaz; kullanıcı kodu, beklenen ReadObject ile CRuntimeClass çağıran tür güvenli ayıklama işlecini çağırmalıdır. Bu, ayıklama işleminin tür bütünlüğünü sigortalar.
WriteObject Uygulama, 1 ile başlayarak artan PID'ler atadığından (0 NULL nesnesi olarak önceden tanımlanmıştır), ReadObject arşiv bağlamının durumunu korumak için bir dizi kullanabilir. Bir PID mağazadan okunduğunda, PID m_pLoadArray geçerli üst sınırından büyükse, ReadObject yeni bir nesnenin (veya sınıf açıklamasının) takip ettiğini bilir.
Şema Numaraları
Sınıfın yöntemiyle karşılaşıldığında IMPLEMENT_SERIAL sınıfına atanan şema numarası, sınıf uygulamasının "sürümüdür". Şema, belirli bir nesnenin kalıcı hale getirilme sayısına (genellikle nesne sürümü olarak adlandırılır) değil, sınıfın uygulanmasına başvurur.
Zaman içinde aynı sınıfın birkaç farklı uygulamasını korumak istiyorsanız, nesnenizin Serialize yöntem uygulamasını düzelttikça şemayı artırmak, uygulamanın eski sürümlerini kullanarak depolanan nesneleri yükleyebilen kod yazmanıza olanak tanır.
yöntemi, CArchive::ReadObject kalıcı depoda bellekteki sınıf açıklamasının şema numarasından farklı bir şema numarasıyla karşılaştığında bir CArchiveException oluşturur. Bu özel durumdan kurtulmak kolay değildir.
Şema sürümünüzü bit düzeyinde VERSIONABLE_SCHEMA işlemiyle birlikte kullanarak bu özel durumun oluşmasını engelleyebilirsiniz.
VERSIONABLE_SCHEMA kullanarak, kodunuz, Serialize'dan gelen dönüş değerini kontrol ederek işlevinde uygun eylemi gerçekleştirebilir.
Serileştirmeyi Doğrudan Çağırmak
Çoğu durumda WriteObject ve ReadObject genel nesne arşivleme düzeninin ek yükü gerekli değildir. Bu, verileri CDocument'a seri hale getirmenin yaygın bir örneğidir. Bu durumda, Serialize yöntemi CDocument ayıklama veya ekleme işleçleriyle değil doğrudan çağrılır. Belgenin içeriği de daha genel nesne arşiv düzenini kullanabilir.
Çağrı Serialize'i doğrudan kullanmanın aşağıdaki avantajları ve dezavantajları vardır:
Nesne seri hale getirilmeden önce veya sonra arşive ek bayt eklenmez. Bu yalnızca kaydedilen verileri küçültmekle kalmaz, aynı zamanda herhangi bir dosya biçimini işleyebilen yordamlar uygulamanıza
Serializeda olanak tanır.MFC,
WriteObjectveReadObjectuygulamalarının ve ilgili koleksiyonların uygulamanıza bağlanmaması için, başka bir amaçla daha genel bir nesne arşiv düzenine ihtiyaç duyulana kadar ayarlanmıştır.Kodunuzun eski şema numaralarından kurtarılması gerekmez. Bu, belge serileştirme kodunuzu şema numaralarını, dosya biçimi sürüm numaralarını veya veri dosyalarınızın başında kullandığınız tanımlayıcı sayıları kodlamaktan sorumlu hale getirir.
Serializeile doğrudan çağrısıyla seri hale getirilen herhangi bir nesne, yaCArchive::GetObjectSchemakullanmamalı veya sürümün bilinmediğini belirten (UINT)-1 dönüş değerini işlemesi gerekir.
Serialize Doğrudan belgenizde çağrıldığından, belgenin alt nesnelerinin ana belge bağlantılarını arşivlemesi genellikle mümkün değildir. Bu nesnelere kapsayıcı belgelerine açıkça bir işaretçi verilmelidir veya bu arka işaretçiler arşivlemeden önce işaretçiyi bir PID'ye eşlemek için CDocument işlevini kullanmanız gerekir.
Daha önce belirtildiği gibi, doğrudan aradığınızda Serialize sürüm ve sınıf bilgilerini kendiniz kodlamanız ve daha sonra eski dosyalarla geriye dönük uyumluluğu korurken biçimi değiştirmenize olanak tanır. İşlev, CArchive::SerializeClass bir nesneyi doğrudan seri hale getirmeden önce veya temel sınıfı çağırmadan önce açıkça çağrılabilir.
Ayrıca bakınız
Numaraya Göre Teknik Notlar
Kategorilere Göre Teknik Notlar