

Программирование на языке MFC
Мой второй блог в серии программирования
Ненулевое значение
Метод производит считывание номера схемы класса и длины названия класса без учета завершающего нулевого байта, после чего в выделенный для названия класса символьный массив читает название класса. Если указанное в архиве число символов в названии класса превышает размер выделенного для него буфера или же при считывании из архива было считано меньше, чем указано, байтов, то метод немедленно возвращает NULL. После того как название класса считано, к нему дописывается нулевой байт, т. е. с этого момента название класса становится обычной строкой, завершающейся нулевым байтом. Затем метод проверяет, описан ли класс, название которого прочитано в архиве, в текущем процессе. Если класс не описан, то метод возвращает значение NULL. Таким образом, если: а) длина имени сохраненного класса равна 64 байтам или больше; б) если при считывании имени класса произошла какая-то ошибка и было считано меньше символов, чем указано; в) класс не описан в вызывающем модуле, то метод CRuntime::Load() возвращает значение NULL. Если же все проверки прошли нормально, то возвращается указатель на информацию времени выполнения того класса, имя которого совпадает и именем считанного из архива класса, и управление опять переходит в метод ReadClassQ. Таким образом, если метод CRuntimeClass::Load() возвратил ненулевое значение, то это является признаком того, что в процессе, осуществляющем чтение из архива, класс, описание которого только что было считано из архива, также описан и процесс готов работать с объектами данного класса.
Если метод CRuntimeClass::Load() вернул значение NULL, это означает, что произошла ошибка, которую метод ReadClass() самостоятельно устранить не в состоянии. Естественный выход для метода ReadClass() в этой ситуации – выработка исключения, что он и делает. Если же загрузка прошла нормально, то начинается проверка соответствия схем (версий) классов, ведь вполне вероятно, что в программе используется описание более новой версии класса, чем сохраненная в архиве, верно?
Если схемы класса в вызывающем модуле и в считанной из архива информации не совпали и при этом не указано, что класс может загружать информацию разных версий, то вырабатывается исключение. В том случае, если схемы не совпадают, но указано, что класс может загружать информацию разных версий, для хранения несовпадающих версий заводится новая хэш-таблица, указатель на нее записывается в поле mjDSchemaMap. Ключами в этой таблице служат указатели на информацию времени выполнения класса, считанного из архива, а значения, которые принимают элементы, равны номерам схем считанных из архива классов. Здесь я не поленюсь лишний раз повторить, что хэш-таблица заводится для хранения ТОЛЬКО тех схем, номера которых НЕ СОВПАДАЮТ со схемой класса, информация о котором передана методу в качестве аргумента.
Раз заведена хэш-таблица, то как же обойтись без проверки числа элементов в ней при помощи метода CheckCount()? А после проверки указатель на информацию времени исполнения класса записывается в очередной свободный элемент массива указателей, который был заведен при вызове метода MapObject(). Естественно, число элементов в этом массиве увеличивается на единицу. *
Тем самым мы завершили обработку описания впервые встретившегося класса. А что происходит в тех случаях, когда мы считываем ссылки на ранее встречавшиеся описания классов? Если индекс ранее встречавшегося класса не равен нулю (если читатель помнит, то нулевой элемент массива инициализируется значением NULL) и не превышает верхнего индекса массива (индекс в таком случае просто лишен смысла), из элемента массива с указанным индексом выбирается информация времени исполнения класса…
Так… А почему мы постоянно говорим о массиве? Дело в том, что индекс, с которым элемент был добавлен в ХЭШ-ТАБЛИЦУ при записи в архив, может использоваться как индекс МАССИВА при считывании из архива. Ведь в данном случае нам не нужно осуществлять массу проверок, верно? И для хранения данных вполне достаточно массива, доступ к элементам которого можно осуществлять по индексам, верно?
Похожие статьи: Load
