|
||||
|
Шаг 4 - О двойной диспетчеризации. Предположим, у нас есть массив, в котором мы храним карту местности. Разумеется, что элементы массива разнообразные - дома, колодцы, казино… ничего общего. Кроме суперкласса - предка естественно. CBuilding ¦ ______¦_______ ¦ ¦ ¦ CHouse CWell CCasino А карту эту мы отражаем разными способами. И даже не то, что разными способами, а имеем для такой благой цели несколько видов карт. Ну я не знаю, не картограф. Черви и пики. Нет, ладно. Радиоактивность и карма. CMap | ____________ | | CRadioMap CCarmaMap И что получается? Кто будет себя отрисовывать? И кто кого? Для каждой комбинации наследников CBuilding и CMap свой уникальный алгоритм. Что делать то будем? Какие феерические решения приходят… нет… не вам! Вашему коллеге или начальнику или подчиненному в голову? Да они ни сном ни духом о двойной диспетчеризации! Они скорее всего предложат получить информацию о типе во время исполнения, и запузырить в Ваш прекрасный проект кривоногий switch (){}. Да еще и положить в каждый класс статический член с информацией о типе… Одно звучание предыдущей фразы наводит на подозрения. Но что делаем мы? вот что: class CBuilding: { public: virtual void doDraw(CMap* map)=0; } class CHouse: public CBuilding { public: virtual void doDraw (CMap* map) { // ВОТ ОНА САМАЯ КОРКА! map-›doDraw(*this); } }; // Эти такие же. class CWell: public CBuilding { public: virtual void doDraw (CMap* map) {map-›doDraw(*this);} }; class CCasino: public CBuilding { public: virtual void doDraw (CMap* map) {map-›doDraw(*this);} }; // Это абстрактный класс для карт. class CMap { public: virtual void doDraw (CHouse& cb)=0; virtual void doDraw (CWell& cb)=0; virtual void doDraw (CCasino& cb)=0; }; Это конечно не все. Теперь нужно наследовать CRadioMap и CcarmaMap от общего предка CMap и в каждом классе рисовать реализацию алгоритма. За отрисовку отвечает карта, но какая масть - решает виртуальная CBuilding::doDraw(), а какое строение - выбирается перегруженная CMap::doDraw(). Одинаковое имя для функций отрисовки в разных классах давать не обязательно, но это является хорошим тоном при двойной диспетчеризации, и плохим без нее. Круто? Это - подвиг неизвестного программиста. У Элджера был разобран пример со сложением чисел, очень красивый, но не сразу понятный. Там числа происходят от одного предка, что левый, что правый операнд оператора +, и по моему, обе диспетчеризации происходят по механизму виртуальных функций. Увы, мне лень набирать код. Код к данному шагу я не проверял, в отличие от предыдущих. К диспетчеризации мы еще вернемся. Или не вернемся. Но следующий шаг однозначно про указатели. |
|
||
Главная | Контакты | Нашёл ошибку | Прислать материал | Добавить в избранное |
||||
|