MFC – Множественное наследование и сериализация - Пробное приложение

ОГЛАВЛЕНИЕ

Пробное приложение

Как пример для приведенной теории было разработано очень простое приложение, показывающее рассмотренную здесь концепцию.

Приложение позволяет создать объект, определенный как классы множественного наследования, и выполнить сериализацию в и из файла. Приложение является приложением MFC, статически связанным с MFC, и с другой статической библиотекой по имени “Utility”, содержащей все классы, не связанные непосредственно с приложением, но относящиеся к общей функциональности. Эту библиотеку можно без ограничений использовать в любом вашем приложении.

Она управляет объектом, созданным на основе этой иерархии наследования:

Зеленые типы могут быть инстанцированы как объекты. Пунктирные линии указывают на виртуальное наследование.

CIntermediate1 может хранить (посредством интеллектуального указателя) производный объект CBase1, и CBase1 хранит обратный указатель на CBase3. То же самое верно для CBase2, CIntermediate2 и CBase3.

Существование интеллектуального указателя члена позволяет создать иерархию инстанцированных объектов. Приложение предоставляет команды, позволяющие создавать объекты разными способами, отображать объекты и сериализовывать их.

Файл demo.test, входящий в пример, содержит данные для создания следующей схемы объектов при загрузке.

и вывод отладки при загрузке файла выглядит так

. 00E18F40: class GE_::Data::CBase0: CBase0 ctor 
. 00E18D70: class GE_::Data::CBase1: CBase1 ctor
. 00E18DB0: class GE_::Data::CBase3: CBase3 ctor
. 00E18D70: class GE_::Data::CIntermediate1: CIntermediate1 ctor
. 00E18E28: class GE_::Data::CBase2: CBase2 ctor
. 00E18E68: class GE_::Data::CBase3: CBase3 ctor
. 00E18E28: class GE_::Data::CIntermediate2: CIntermediate2 ctor
. 00E18D70: class GE_::Data::CAssembled: CAssembled ctor
. 00E18D70: class GE_::Data::CAssembled: CAssembled::Serialize
.. 00E18D70: class GE_::Data::CAssembled: CIntermediate1::Serialize
... 00E18D70: class GE_::Data::CAssembled: CBase1::Serialize
.... 00E18F40: class GE_::Data::CAssembled: CBase0::Serialize
... 00E18DB0: class GE_::Data::CAssembled: CBase3::Serialize
... 00E19938: class GE_::Data::CBase0: CBase0 ctor
... 00E19768: class GE_::Data::CBase1: CBase1 ctor
... 00E197A8: class GE_::Data::CBase3: CBase3 ctor
... 00E19768: class GE_::Data::CIntermediate1: CIntermediate1 ctor
... 00E19820: class GE_::Data::CBase2: CBase2 ctor
... 00E19860: class GE_::Data::CBase3: CBase3 ctor
... 00E19820: class GE_::Data::CIntermediate2: CIntermediate2 ctor
... 00E19768: class GE_::Data::CAssembled: CAssembled ctor
... 00E19768: class GE_::Data::CAssembled: CAssembled::Serialize
.... 00E19768: class GE_::Data::CAssembled: CIntermediate1::Serialize
..... 00E19768: class GE_::Data::CAssembled: CBase1::Serialize
...... 00E19938: class GE_::Data::CAssembled: CBase0::Serialize
..... 00E197A8: class GE_::Data::CAssembled: CBase3::Serialize
..... 00E1A244: class GE_::Data::CBase0: CBase0 ctor
..... 00E1A160: class GE_::Data::CBase1: CBase1 ctor
..... 00E1A1A0: class GE_::Data::CBase3: CBase3 ctor
..... 00E1A160: class GE_::Data::CIntermediate1: CIntermediate1 ctor
..... 00E1A160: class GE_::Data::CIntermediate1: CIntermediate1::Serialize
...... 00E1A160: class GE_::Data::CIntermediate1: CBase1::Serialize
....... 00E1A244: class GE_::Data::CIntermediate1: CBase0::Serialize
...... 00E1A1A0: class GE_::Data::CIntermediate1: CBase3::Serialize
...... 00E1A974: class GE_::Data::CBase0: CBase0 ctor
...... 00E1A890: class GE_::Data::CBase1: CBase1 ctor
...... 00E1A8D0: class GE_::Data::CBase3: CBase3 ctor
...... 00E1A890: class GE_::Data::CIntermediate1: CIntermediate1 ctor
...... 00E1A890: class GE_::Data::CIntermediate1: CIntermediate1::Serialize
....... 00E1A890: class GE_::Data::CIntermediate1: CBase1::Serialize
........ 00E1A974: class GE_::Data::CIntermediate1: CBase0::Serialize
....... 00E1A8D0: class GE_::Data::CIntermediate1: CBase3::Serialize
.... 00E19820: class GE_::Data::CAssembled: CIntermediate2::Serialize
..... 00E19820: class GE_::Data::CAssembled: CBase2::Serialize
..... 00E19860: class GE_::Data::CAssembled: CBase3::Serialize
..... 00E1B340: class GE_::Data::CBase0: CBase0 ctor
..... 00E1B170: class GE_::Data::CBase1: CBase1 ctor
..... 00E1B1B0: class GE_::Data::CBase3: CBase3 ctor
..... 00E1B170: class GE_::Data::CIntermediate1: CIntermediate1 ctor
..... 00E1B228: class GE_::Data::CBase2: CBase2 ctor
..... 00E1B268: class GE_::Data::CBase3: CBase3 ctor
..... 00E1B228: class GE_::Data::CIntermediate2: CIntermediate2 ctor
..... 00E1B170: class GE_::Data::CAssembled: CAssembled ctor
..... 00E1B170: class GE_::Data::CAssembled: CAssembled::Serialize
...... 00E1B170: class GE_::Data::CAssembled: CIntermediate1::Serialize
....... 00E1B170: class GE_::Data::CAssembled: CBase1::Serialize
........ 00E1B340: class GE_::Data::CAssembled: CBase0::Serialize
....... 00E1B1B0: class GE_::Data::CAssembled: CBase3::Serialize
....... 00E1BD30: class GE_::Data::CBase0: CBase0 ctor
....... 00E1BB60: class GE_::Data::CBase1: CBase1 ctor
....... 00E1BBA0: class GE_::Data::CBase3: CBase3 ctor
....... 00E1BB60: class GE_::Data::CIntermediate1: CIntermediate1 ctor
....... 00E1BC18: class GE_::Data::CBase2: CBase2 ctor
....... 00E1BC58: class GE_::Data::CBase3: CBase3 ctor
....... 00E1BC18: class GE_::Data::CIntermediate2: CIntermediate2 ctor
....... 00E1BB60: class GE_::Data::CAssembled: CAssembled ctor
....... 00E1BB60: class GE_::Data::CAssembled: CAssembled::Serialize
........ 00E1BB60: class GE_::Data::CAssembled: CIntermediate1::Serialize
......... 00E1BB60: class GE_::Data::CAssembled: CBase1::Serialize
.......... 00E1BD30: class GE_::Data::CAssembled: CBase0::Serialize
......... 00E1BBA0: class GE_::Data::CAssembled: CBase3::Serialize
........ 00E1BC18: class GE_::Data::CAssembled: CIntermediate2::Serialize
......... 00E1BC18: class GE_::Data::CAssembled: CBase2::Serialize
......... 00E1BC58: class GE_::Data::CAssembled: CBase3::Serialize
...... 00E1B228: class GE_::Data::CAssembled: CIntermediate2::Serialize
....... 00E1B228: class GE_::Data::CAssembled: CBase2::Serialize
....... 00E1B268: class GE_::Data::CAssembled: CBase3::Serialize
.. 00E18E28: class GE_::Data::CAssembled: CIntermediate2::Serialize
... 00E18E28: class GE_::Data::CAssembled: CBase2::Serialize
... 00E18E68: class GE_::Data::CAssembled: CBase3::Serialize
... 00E1CC6C: class GE_::Data::CBase0: CBase0 ctor
... 00E1CB88: class GE_::Data::CBase2: CBase2 ctor
... 00E1CBC8: class GE_::Data::CBase3: CBase3 ctor
... 00E1CB88: class GE_::Data::CIntermediate2: CIntermediate2 ctor
... 00E1CB88: class GE_::Data::CIntermediate2: CIntermediate2::Serialize
.... 00E1CB88: class GE_::Data::CIntermediate2: CBase2::Serialize
..... 00E1CC6C: class GE_::Data::CIntermediate2: CBase0::Serialize
.... 00E1CBC8: class GE_::Data::CIntermediate2: CBase3::Serialize
.... 00E1D39C: class GE_::Data::CBase0: CBase0 ctor
.... 00E1D2B8: class GE_::Data::CBase2: CBase2 ctor
.... 00E1D2F8: class GE_::Data::CBase3: CBase3 ctor
.... 00E1D2B8: class GE_::Data::CIntermediate2: CIntermediate2 ctor
.... 00E1D2B8: class GE_::Data::CIntermediate2: CIntermediate2::Serialize
..... 00E1D2B8: class GE_::Data::CIntermediate2: CBase2::Serialize
...... 00E1D39C: class GE_::Data::CIntermediate2: CBase0::Serialize
..... 00E1D2F8: class GE_::Data::CIntermediate2: CBase3::Serialize
       

Обратите внимание, что:

•    CBase1, CIntermediate1 и CAssembled в одном и том же экземпляре имеют один и тот же адрес, но CBase0 (виртуальный) и CBase3 (и CBase2, и CIntermediate2 в CAssembled) имеют разные адреса (они не первые базовые классы: при создании полиморфного объекта MFC ожидает, что все базовые классы имеют один и тот же адрес, оттого нужны отдельные карты)
•    В CAssebled есть два CBase3, но они имеют разные адреса
•    Конструкторы выглядят линейными (без отступов): причина состоит в том, что конструкторы базовых классов вызываются автоматически перед входом в конструкторы производных классов. Вызовы сериализации имеют отступы, потому что они вызываются вложенно.

Как было сказано в начале, MFC не переделывалась. Возможно, тема непростая, но использование решения должно облегчить ее. Все-таки все сводится к написанию очень маленького кода в функциях сериализации (добавить две строки или вызвать один макрос – остается на ваше усмотрение).