Программирование на языке MFC

Мой второй блог в серии программирования

Метод CRuntimeClass::Load


Практически сразу после вызова ReadClassQ вызывает ме­тод MapObject() с параметром NULL. Но обратите внимание, чи­татель, на то, что в случае чтения информации из архива соз­дается не хэш-таблица, а МАССИВ указателей. Указатель на массив записывается в поле m_pLoadArray, которое, кстати, опи­сано в одном объединении (union’e) с полем m_pStoreMap. После этого в архиве создается один элемент, в который записывается значение NULL. Естественно, счетчик элементов массива, т. е. значение поля m_nMapCount, тоже делается равным одному. Как и в случае сохранения информации в массиве, при аргументе, равном NULL метод больше ничего не делает. Таким образом, вызов метода MapObject() с параметром NULL при чтении из архива приводит к созданию и инициализации массива указателей.

Затем метод ReadClass() начинает работу в точном соответствии с тем списком правил, который мы сформировали в конце предыду­щего раздела. В том случае, если считан тэг объекта, то метод записывает тэг объекта по адресу, переданному ему в качестве третьего аргумента, и возвращает значение NULL. Отметим этот факт – метод ReadClassQ в том случае, если из архива считан тэг объекта, возвращает значение NULL. У объекта схемы (версии) быть не может, поэтому мы не заполняем указатель на схему. Однако если из архива считан тэг класса, нам придется немного повозиться с этим тэгом.

Давайте рассуждать. Если встречен тэг класса, то какие случаи должны быть рассмотрены при этом? Наверное, должны быть рас­смотрены два случая: 1) считан тэг ранее не встречавшегося клас­са и 2) считана ссылка на тэг ранее встречавшегося в процессе считывания класса. В том случае, если метод ReadClass() считал из архива тэг ранее не встречавшегося класса, то он должен загрузить информацию времени выполнения этого класса, после чего осуществить все необходимые проверки, верно? Информация вре­мени выполнения загружается при помощи метода CRuntimeClass::Load(), исходный текст которого можно найти в файле агссоге.срр:

CRuntimeClass* PASCAL CRuntimeClass::Load(CArchive& ar,

UINT*’pwSchemaNum)

// loads a runtime class description

{

WORD nLen;

char szClassName[64]; CRuntimeClass* pClass;

WORD wTemp;

ar >> wTemp; *pwSchemaNum = wTemp; ar >> nLen;

if (nLen >= _countof(szClassName) ||

ar.Read(szClassName, nLen*sizeof(char)) !=

nLen*sizeof(char))

{

return NULL;

}

szClassName[nLen] = Л\0′;

// search app specific classes

AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); AfxLockGlobals(CRIT_RUNTIMECLASSLIST);

for (pClass = pModuleState->m_classList; pClass != NULL; pClass = pClass->m_pNextClass)

{

if (IstrcmpA(szClassName,

pClass->m_lpszClassName) == 0)

{

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST); return pClass;

}

}

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

#ifdef _AFXDLL

// search classes in shared DLLs AfxLockGlobals(CRITJDYNLINKLIST);

for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL; pDLL = pDLL->m_pNextDLL)

{

for (pClass = pDLL->m_classList; pClass != NULL; pClass = pClass->m_pNextClass)

{

if (IstrcmpA(szClassName,

pClass->m_lpszClassName) == 0)

{

AfxUnlockGlobals(CRIT_DYNLINKL1ST) ; return pClass;

}

}

}

AfxUnlockGlobals(CRIT_DYNLINKLIST); #endif

TRACE1 ("’Warning: Cannot load %hs from archive.

Class not defined.\n", szClassName);

return NULL; // not found

}

В тексте этого метода нужно обратить внимание на одну ме­лочь: для чтения названия класса выделяется буфер размером 64 байта. Следовательно, название класса не может быть длин­нее 64 символов.

Похожие статьи: ,