Ѕаза знаний студента. –еферат, курсова€, контрольна€, диплом на заказ

курсовые,контрольные,дипломы,рефераты

»нтерфейсы как решение проблем множественного наследовани€ — »нформатика, программирование

ѕосмотреть видео по теме ƒоклада

≈вгений  аратаев

¬ этой работе разбираетс€ проблема множественного наследовани€ в €зыке программировани€ —++ и возможное ее решение путем применени€ абстракций интерфейсов.

ћножественным наследованием €вл€етс€ образование класса путем наследовани€ одновременно нескольких базовых классов. Ўтука полезна€ и одновременно с этим проблемна€. –азберем пример, в котором по€вл€етс€ множественное наследование, привод€щее к проблеме.

 лассическим заданием дл€ начинающего программиста €вл€етс€ задача написать классы, реализующие иерархию „еловек - —тудент - —отрудник. ќбычно первым же решением есть образование трех классов в виде:

class „еловек { ... };

class —отрудник : public „еловек { ... };

class —тудент : public „еловек { ... };

¬ классе „еловек декларируютс€ несколько виртуальных и, возможно, абстрактных, функций, которые переопредел€ютс€ / реализуютс€ в классах-наследниках. —хема на первый взгл€д совершенно очевидна и практически ни у кого не вызывает подозрений. —хема реализуетс€ в программе и программа сдаетс€ в работу.

ѕроблема возникает позже, когда оператор приходит и говорит:

- ” мен€ есть человек, который одновременно и сотрудник и студент. „то мне делать?

–еализованна€ схема, вообще говор€, не предполагает такого варианта - могут быть либо сотрудник, либо студент. Ќо что-то делать надо. ¬ этот момент приходит на помощь множественное наследование. ѕрограммист, не долго дума€, создает еще один класс, образованный наследованием и от —отрудник и от —тудент:

class —тудент—отрудник : public —тудент, public —отрудник { ...};

Ќа первый взгл€д все в пор€дке, на второй - полный бардак. ƒело в том, что класс —отрудник, как он был декларирован, содержит в себе полную копию класса „еловек. “о же самое относитс€ и к классу —тудент. “аким образом, класс —тудент—отрудник будет содержать в себе уже 2 копии класса „еловек. ѕри этом функции класса —отрудник будут работать со своим экземпл€ром класса „еловек, а функции класса —тудент - со своим. ¬ результате корректного поведени€ добитьс€ практически очень трудно. ¬ классе —тудент—отрудник придетс€ переопредел€ть все функции базовых классов и вызывать соответствующие функции базовых классов, чтобы модификации обеих копий класса „еловек прошли когерентно.

ќбнаружив такую ситуацию путем т€желой отладки, программист приходит к необходимости применени€ виртуального наследовани€ дл€ исключени€ дублировани€ класса „еловек. ѕроблема состоит в том, что виртуальное наследование требует модификации графа наследовани€ базовых классов. “ребуема€ схема имеет вид:

class „еловек { ... };

class —тудент : virtual public „еловек { ... };

class —отрудник : virtual public „еловек { ... };

class —тудент—отрудник : public —тудент, public —отрудник { ...

};

¬ этом варианте решена проблема однозначной входимости класса „еловек во все классы. Ќо остаетс€ вопрос - не возникнет ли такой же проблемы и дальше с полученным классом —тудент—отрудник? » будет ли возможность произвести модификацию уже работающего кода? ¬ такой ситуации руки могут опуститьс€ - следует либо согласитьс€ с существованием проблемного кода либо действительно идти на полную переработку программы.

“ем не менее элегантное решение существует. Ёто реализаци€ базовых классов по принципу интерфейсов. язык —++ не содержит €зыковой поддержки интерфейсов в €вном виде, поэтому будем их эмулировать. ѕринцип интерфейса состоит в том, что его задачей €вл€етс€ не столько реализаци€ класса, сколько его деклараци€. Ќормализуем исходную задачу:

class Ѕыть„еловеком { ... };

class Ѕыть—тудентом { ... };

class Ѕыть—отрудником { ... };

»сход€ из нормализованного множества классов, получим дополнение:

class „еловек : public Ѕыть„еловеком { ... };

class —отрудник : public Ѕыть„еловеком, public Ѕыть—отрудником { ... };

class —тудент : public Ѕыть„еловеком, public Ѕыть—тудентом { ...};

class —тудент—отрудник : public Ѕыть„еловеком, public Ѕыть—тудентом,

†† public Ѕыть—отрудником { ... };

‘ормально говор€, така€ схема построени€ классов вполне работоспособна за исключением того, что во многих случа€х программисты относ€тс€ к интерфейсам слишком уж буквально - оставл€ют в них только абстрактные функции и реализуют эти функции только в классах-наследниках. ¬ результате полностью выхолащиваетс€ иде€ повторного использовани€ кода. ќснованием дл€ нереализации функций в интерфейсных классах обычно служит то, что в классе - интерфейсе нет "€дра" объекта. ¬ нашем случае €дром объекта или классом, реализующим возможность существовани€ объекта, может выступать класс Ѕыть„еловеком.

¬озможным решением проблемы €вл€етс€ передача конструктору интерфейсного класса указател€ на конструируемый объект с тем, чтобы его запомнить в своем частном поле данных и использовать при реализации функций интерфейса. ѕримерно по схеме:

class Ѕыть—тудентом

{

†† Ѕыть„еловеком& m_Ѕыть„еловеком;

†† public:

†† Ѕыть—тудентом( Ѕыть„еловеком& init)

†† : m_Ѕыть„еловеком( init)

†† { ... };

};

class —тудент : public Ѕыть„еловеком, public Ѕыть—тудентом

{

†† public:

†† —тудент()

†† : Ѕыть„еловеком(), Ѕыть—тудентом( *this)

†† { ...};

};

¬ этой схеме, согласно стандарту, также есть проблема - стандарт не гарантирует инициализации конструкторов, указанных в списке инициализации, в том пор€дке, в котором они перечислены в этом списке. ѕоэтому мы, передава€ *this как аргумент конструктора базового класса, получаем ссылку на негарантированно определенный объект. ¬ыйти из этой ситуации можно, если декларировать конструктор без аргументов и создать дополнительную функцию инициализации, завис€щую от *this. Ќо дублирование ссылок, хранимых в интерфейсных классах, тем не менее, сохран€етс€ и это есть некрасиво.

ƒл€ решени€ этой задачи есть чрезвычайно красивое, на мой взгл€д, решение. –ешение заключаетс€ в том, чтобы не хранить ссылку на €дро объекта, а получать ее динамически. ƒл€ этого примен€етс€ оператор приведени€ типа dynamic_cast, примен€емый не к классу, а к объекту в процессе работы программы. ѕример:

class Ѕыть—тудентом

{

†† public:

††††† Ѕыть—тудентом(){};

††††† virtual void Func( void);

††††† // пример функции, обращающейс€ к €дру объекта

††††† {

†††††††† Ѕыть„еловеком* ptr = dynamic_cast< Ѕыть„еловеком* >( this);

†††††††† if( ptr)

†††††††† {

††††††††††† // используем €дро

†††††††† }

††††† };

};

Ќа первый взгл€д, приведение типа Ѕыть—тудентом к типу Ѕыть„еловеком невозможно, поскольку никто их этих классов ни от кого не наследован. Ќо дело в том, что оператор dynamic_cast определен не дл€ классов, а дл€ объектов. » если при исполнении кода Func реальный объект, дл€ которого эта функци€ выполн€етс€, имееет класс, унаследованый от Ѕыть„еловеком, то оператор вернет правильное значение. —огласно стандарту, оператор приведени€ типа dynamic_cast имеет два вида поведени€ если приведение невозможно - вернуть нулевое значение либо возбудить исключительную ситуацию. ќба варианта нас полностью устраивают.

я считаю, что в модели применени€ интерфейсных классов дл€ решени€ проблем множественного наследовани€ будет также красиво построить интерфейсные классы с конструкторами, не требующими обращени€ к €дру объекта. ¬прочем, это уже из области философии помехоустойчивого программировани€.


≈вгений  аратаев ¬ этой работе разбираетс€ проблема множественного наследовани€ в €зыке программировани€ —++ и возможное ее решение путем применени€ абстракций интерфейсов. ћножественным наследованием €вл€етс€ образование класса путем наследо

 

 

 

¬нимание! ѕредставленный ƒоклад находитс€ в открытом доступе в сети »нтернет, и уже неоднократно сдавалс€, возможно, даже в твоем учебном заведении.
—оветуем не рисковать. ”знай, сколько стоит абсолютно уникальный ƒоклад по твоей теме:

Ќовости образовани€ и науки

«аказать уникальную работу

ѕохожие работы:

ѕерспективные архитектуры генетического поиска
ћикроконтент: как писать заголовки, заглави€ страниц и темы в почтовых сообщени€х
ѕоиск подстроки в строке с помощью хеш-функции
¬ласть народу - относительные размеры шрифтов
CSS дизайн: с учетом контекста
ѕоиск того, чего нет
–абота с инифайлами (ini)
јутсорсинг тестировани€ Ч точим чужое оружие
»нструменты необходимые дл€ тестировани€ Linux
ѕроблемы интеграции: Mercury Interactive QuickTest & TestDirector

—вои сданные студенческие работы

присылайте нам на e-mail

Client@Stud-Baza.ru