Доклад: Интерфейсы как решение проблем множественного наследования

Доклад: Интерфейсы как решение проблем множественного наследования




⚡ 👉🏻👉🏻👉🏻 ИНФОРМАЦИЯ ДОСТУПНА ЗДЕСЬ ЖМИТЕ 👈🏻👈🏻👈🏻




























































В этой работе разбирается проблема множественного наследования в языке программирования С++ и возможное ее решение путем применения абстракций интерфейсов.
Множественным наследованием является образование класса путем наследования одновременно нескольких базовых классов. Штука полезная и одновременно с этим проблемная. Разберем пример, в котором появляется множественное наследование, приводящее к проблеме.
Классическим заданием для начинающего программиста является задача написать классы, реализующие иерархию Человек - Студент - Сотрудник. Обычно первым же решением есть образование трех классов в виде:
class Сотрудник : public Человек { ... };
class Студент : public Человек { ... };
В классе Человек декларируются несколько виртуальных и, возможно, абстрактных, функций, которые переопределяются / реализуются в классах-наследниках. Схема на первый взгляд совершенно очевидна и практически ни у кого не вызывает подозрений. Схема реализуется в программе и программа сдается в работу.
Проблема возникает позже, когда оператор приходит и говорит:
- У меня есть человек, который одновременно и сотрудник и студент. Что мне делать?
Реализованная схема, вообще говоря, не предполагает такого варианта - могут быть либо сотрудник, либо студент. Но что-то делать надо. В этот момент приходит на помощь множественное наследование. Программист, не долго думая, создает еще один класс, образованный наследованием и от Сотрудник и от Студент:
class СтудентСотрудник : public Студент, public Сотрудник { ...};
На первый взгляд все в порядке, на второй - полный бардак. Дело в том, что класс Сотрудник, как он был декларирован, содержит в себе полную копию класса Человек. То же самое относится и к классу Студент. Таким образом, класс СтудентСотрудник будет содержать в себе уже 2 копии класса Человек. При этом функции класса Сотрудник будут работать со своим экземпляром класса Человек, а функции класса Студент - со своим. В результате корректного поведения добиться практически очень трудно. В классе СтудентСотрудник придется переопределять все функции базовых классов и вызывать соответствующие функции базовых классов, чтобы модификации обеих копий класса Человек прошли когерентно.
Обнаружив такую ситуацию путем тяжелой отладки, программист приходит к необходимости применения виртуального наследования для исключения дублирования класса Человек. Проблема состоит в том, что виртуальное наследование требует модификации графа наследования базовых классов. Требуемая схема имеет вид:
class Студент : virtual public Человек { ... };
class Сотрудник : virtual public Человек { ... };
class СтудентСотрудник : public Студент, public Сотрудник { ...
В этом варианте решена проблема однозначной входимости класса Человек во все классы. Но остается вопрос - не возникнет ли такой же проблемы и дальше с полученным классом СтудентСотрудник? И будет ли возможность произвести модификацию уже работающего кода? В такой ситуации руки могут опуститься - следует либо согласиться с существованием проблемного кода либо действительно идти на полную переработку программы.
Тем не менее элегантное решение существует. Это реализация базовых классов по принципу интерфейсов. Язык С++ не содержит языковой поддержки интерфейсов в явном виде, поэтому будем их эмулировать. Принцип интерфейса состоит в том, что его задачей является не столько реализация класса, сколько его декларация. Нормализуем исходную задачу:
Исходя из нормализованного множества классов, получим дополнение:
class Человек : public БытьЧеловеком { ... };
class Сотрудник : public БытьЧеловеком, public БытьСотрудником { ... };
class Студент : public БытьЧеловеком, public БытьСтудентом { ...};
class СтудентСотрудник : public БытьЧеловеком, public БытьСтудентом,
Формально говоря, такая схема построения классов вполне работоспособна за исключением того, что во многих случаях программисты относятся к интерфейсам слишком уж буквально - оставляют в них только абстрактные функции и реализуют эти функции только в классах-наследниках. В результате полностью выхолащивается идея повторного использования кода. Основанием для нереализации функций в интерфейсных классах обычно служит то, что в классе - интерфейсе нет "ядра" объекта. В нашем случае ядром объекта или классом, реализующим возможность существования объекта, может выступать класс БытьЧеловеком.
Возможным решением проблемы является передача конструктору интерфейсного класса указателя на конструируемый объект с тем, чтобы его запомнить в своем частном поле данных и использовать при реализации функций интерфейса. Примерно по схеме:
БытьСтудентом( БытьЧеловеком& init)
class Студент : public БытьЧеловеком, public БытьСтудентом
: БытьЧеловеком(), БытьСтудентом( *this)
В этой схеме, согласно стандарту, также есть проблема - стандарт не гарантирует инициализации конструкторов, указанных в списке инициализации, в том порядке, в котором они перечислены в этом списке. Поэтому мы, передавая *this как аргумент конструктора базового класса, получаем ссылку на негарантированно определенный объект. Выйти из этой ситуации можно, если декларировать конструктор без аргументов и создать дополнительную функцию инициализации, зависящую от *this. Но дублирование ссылок, хранимых в интерфейсных классах, тем не менее, сохраняется и это есть некрасиво.
Для решения этой задачи есть чрезвычайно красивое, на мой взгляд, решение. Решение заключается в том, чтобы не хранить ссылку на ядро объекта, а получать ее динамически. Для этого применяется оператор приведения типа dynamic_cast, применяемый не к классу, а к объекту в процессе работы программы. Пример:
// пример функции, обращающейся к ядру объекта
БытьЧеловеком* ptr = dynamic_cast< БытьЧеловеком* >( this);
На первый взгляд, приведение типа БытьСтудентом к типу БытьЧеловеком невозможно, поскольку никто их этих классов ни от кого не наследован. Но дело в том, что оператор dynamic_cast определен не для классов, а для объектов. И если при исполнении кода Func реальный объект, для которого эта функция выполняется, имееет класс, унаследованый от БытьЧеловеком, то оператор вернет правильное значение. Согласно стандарту, оператор приведения типа dynamic_cast имеет два вида поведения если приведение невозможно - вернуть нулевое значение либо возбудить исключительную ситуацию. Оба варианта нас полностью устраивают.
Я считаю, что в модели применения интерфейсных классов для решения проблем множественного наследования будет также красиво построить интерфейсные классы с конструкторами, не требующими обращения к ядру объекта. Впрочем, это уже из области философии помехоустойчивого программирования.

Название: Интерфейсы как решение проблем множественного наследования
Раздел: Рефераты по информатике, программированию
Тип: доклад
Добавлен 07:04:26 23 марта 2005 Похожие работы
Просмотров: 373
Комментариев: 16
Оценило: 5 человек
Средний балл: 4.6
Оценка: неизвестно   Скачать

Срочная помощь учащимся в написании различных работ. Бесплатные корректировки! Круглосуточная поддержка! Узнай стоимость твоей работы на сайте 64362.ru
Привет студентам) если возникают трудности с любой работой (от реферата и контрольных до диплома), можете обратиться на FAST-REFERAT.RU , я там обычно заказываю, все качественно и в срок) в любом случае попробуйте, за спрос денег не берут)
Да, но только в случае крайней необходимости.

Доклад: Интерфейсы как решение проблем множественного наследования
Смак Май Эсс
Отчет по практике: Структура туристической фирмы "Турист" и специфика ее работы
Реферат по теме Буддизм і сучасне мислення
Реферат: Перспективы развития и применения нанотехнологий. Углеродные нанотрубки Ђ“ революция в сфере технологии наночастиц. Скачать бесплатно и без регистрации
Клиническая Смерть Реферат Первая Помощь
Контрольная работа по теме Плательщики обязательных страховых взносов в Фонд социальной защиты населения Республики Беларусь. Пути реформирования налоговой системы
Реферат по теме Проект комплексного автотранспортного предприятия
Реферат по теме Великие владимирцы - братья Столетовы
Дипломная работа по теме Оценка рыночной стоимости однокомнатной квартиры
Реферат по теме Научно-технический прогресс и научное производство
Курсовая работа по теме Роль государства в стимулировании экспорта
Докторская диссертация
Көшпелі Мәдениет Эссе
Практическая Работа План
Реферат по теме Рынок кофе
Реферат: Libel And Invasion Of Privacy Essay Research
Реферат по теме Осмометр – прибор для измерения осмотического давления
Напишите Сочинение Гимн Русской Зиме
Дипломная работа по теме Автоматизация учета клиентов организации средствами программы '1С: Предприятие 7.7'
Дипломная работа по теме Потребительский кредит и его роль в развитии национальной экономики повышении жизненного уровня населения (на примере организации ОАО 'Альфа-Бан')
Реферат: Марс
Сочинение: Карамзин Н. М.
Реферат: Комплексный анализ себестоимости продукции

Report Page