

Программирование на языке MFC
Мой второй блог в серии программирования
Метод ReadClass
После того, что мы узнали о записи объекта в архив, мы можем догадаться, что первым делом метод ReadObject() постарается считать данные о классе объекта. Как видно из текста метод, так оно и происходит. Для считывания информации о классе используется метод ReadClass(). Исходный код этого метода находится в файле afxobj.cpp:
CRuntimeClass* CArchive::ReadClass(const
CRuntimeClass* pClassRefRequested, UINT* pSchema, DWORD* pObTag)
{
ASSERT(pClassRefRequested == NULL || AfxIsValidAddress(pClassRefRequested,
sizeof(CRuntimeClass), FALSE));
ASSERT(IsLoading()); // proper direction
if (pClassRefRequested != NULL &&
pClassRefRequested->m_wSchema == OxFFFF)
{
TRACE1("Warning: Cannot call ReadClass/ReadObject
for %hs.\n", pClassRefRequested->m_lpszClassName); AfxThrowNotSupportedException ();
}
// make sure m_pLoadArray is initialized MapObject(NULL);
// read object tag – if prefixed by wBigObjectTag // then DWORD tag follows
DWORD obTag;
WORD wTag;
*this >> wTag;
if (wTag == wBigObjectTag) *this » obTag;
else
obTag = ( (wTag & wClassTag) « 16) | (wTag & -wClassTag);
// check for object tag (throw exception if // expecting class* tag)
if (!(obTag & dwBigClassTag)) {
if (pObTag == NULL)
AfxThrowArchiveException(CArchiveException::badlndex,
m_strFileName);
*pObTag = obTag; return NULL;
CRuntimeClass* pClassRef;
UINT nSchema;
if (wTag == wNewClassTag)
{
// new object follows a new class id
if ((pClassRef = CRuntimeClass::Load(*this,
&nЈchema)) == NULL) AfxThrowArchiveException(CArchiveException::badClass,
m_strFileName);
// check nSchema against the expected schema if ((pClassRef->m_wSchema &
~VERSIONABLE_SCHEMA) != nSchema)
{
if (! (pClassRef->m_wSchema & VERSIONABLE_SCHEMA) ) {
// schema doesn’t match and not marked as VERSIONABLE_SCHEMA Af xThrowArchiveException (CArchiveException: :badSchema,
m_strFileName);
}
else {
// they differ — store the schema for later retrieval if (m_pSchemaMap == NULL)
m_pSchemaMap = new CMapPtrToPtr; ASSERT_VALID(m_pSchemaMap);
m_pSchemaMap->SetAt(pClassRef, (void*)nSchema) ;
}
}
CheckCount ();
m_pLoadArray->InsertAt(m_nMapCount++, pClassRef) ;
}
else {
// existing class index in obTag followed by new object DWORD nClassIndex = (obTag & -dwBigClassTag); if (nClassIndex == 0 I I
nClassIndex > (DWORD)m_pLoadArray->GetUpperBound() ) AfxThrowArchiveException(CArchiveException::badlndex,
m_strFileName);
pClassRef =
(CRuntimeClass*)m_pLoadArray->GetAt(nClassIndex); ASSERT(pClassRef !=NULL);
// determine schema stored against objects of this type void* pTemp; BOOL bFound = FALSE; nSchema = 0;
if (m_pSchemaMap != NULL) {
bFound = m_pSchemaMap->Lookup( pClassRef, pTemp ); if (bFound)
nSchema = (UINT)pTemp;
}
if (!bFound)
nSchema = pClassRef->m_wSchema & ~VERSIONABLE_SCHEMA;
}
// check for correct derivation if (pClassRefRequested != NULL &&
!pClassRef->IsDerivedFrom(pClassRefRequested))
{
AfxThrowArchiveException(CArchiveException::badClass,
m_strFileName);
}
// store nSchema for later examination if (pSchema != NULL)
*pSchema = nSchema; else
m_nObjectSchema = nSchema;
// store obTag for later examination if (pObTag != NULL) *pObTag = obTa^;
// return the resulting CRuntimeClass* return pClassRef;
}
В качестве аргументов методу передается указатель на информацию времени выполнения класса, а также ссылки на два поля, которые будут заполнены значениями, считанными из архива. В поле pSchema будет записана схема (версия) класса, а в поле obTag будет записан тэг объекта, каким он был записан в архив. Смысл передачи ссылки на схему и на тэг объекта понятен. А зачем мы передаем указатель на информацию времени выполнения класса? Дело обстоит очень просто. Вполне вероятно, что наша программа уже изменилась и чо в нашей программе класс, который мы готовимся считать из архива, просто не описан, верно? Или, скажем, мы по ошибке открыли архив, созданный другой программой, или… Да мало ли что может приключиться! Мы должны убедиться в том, что мы считываем из архива объект именно того класса, о котором у нас есть информация, верно?
Похожие статьи: Метод Read
