Шаг 14 - Двойная диспетчеризация. Продолжение.
Шаг 14 - Двойная диспетчеризация. Продолжение.
В Шаге 4 мы говорили о двойной диспетчеризации. Она очень хорошо подходит при необходимости отображения одних объектов посредством других, но не только; она в общем применима, когда Вам нужно обрабатывать попарные (и более) взаимодействия объектов двух и более разных классов. Получается этакая табличка, на осях которой нарисованы классы, а в ячейках - функции их взаимодействия. Количество функций равно произведению столбцов и строк этой таблички. А если диспетчеризация тройная или выше? Тогда еще умножаем на количество слоев, и дальше и дальше…
Как бы упростить жизнь? А вот так - если взаимодействие двух объектов дает один результат, пусть этим и занимается одна функция. Попробуем перевести на человеческий язык:
Пусть есть класс CTitanic и класс CIceberg. Их карма в том, чтобы столкнуться. Четыре варианта взаимодействия: Столкновение двух Ctitanic не ведет ни к чему, если вообще возможно, двух CIceberg - у них там свои дела, столкновение CTitanic и CIceberg, как известно, к семи Оскарам, и столкновение CIceberg и CTitanic - к тому же самому. То есть функций всего три. Определим взаимодействие этих классов как функцию hit(). Вот код:
#include ‹iostream.h›
// Форвардные объявления
class CTitanic;
class CIceberg;
class CFloating;
// Абстрактный базовый класс
class CFloating {
public:
virtual void hit(CIceberg&)=0;
virtual void hit(CTitanic&)=0;
public:
virtual void hit(CFloating&)=0;
};
// Класс айсберга
class CIceberg {
public:
virtual void hit(CIceberg&);
virtual void hit(CTitanic&);
public:
virtual void hit(CFloating&);
};
// Первая диспетчерская функция
void CIceberg::hit(CFloating& _co) {
_co.hit(*this);
}
// Две реализации взаимодействия
void CIceberg::hit(CIceberg& _ci) {
cout ‹‹ "ci+ci" ‹‹ endl;
}
void CIceberg::hit(CTitanic& _ct) {
cout ‹‹ "ci+co" ‹‹ endl;
}
// Класс Титаника
class CTitanic {
public:
virtual void hit(CIceberg&);
virtual void hit(CTitanic&);
public:
virtual void hit(CFloating&);
};
// Еще одна диспетчерская функция
void CTitanic::hit(CFloating& _co) { _co.hit(*this); }
// А вот эта функция могла бы быть реализацией
// но мы ее тоже делаем диспетчерской;
// в этом фрагменте диспетчеризация тройная.
void CTitanic::hit(CIceberg& _ci) {
// cout ‹‹ "co+ci" ‹‹ endl; Это могла быть реализация
_ci.hit(*this);
}
void CTitanic::hit(CTitanic& _ct) {
cout ‹‹ "co+co" ‹‹ endl;
}
// проверим по быстрому, как работает
int main () {
CIceberg i1;
CTitanic t1;
CIceberg i2;
CTitanic t2;
i1.hit(t1);
i1.hit(i2);
t1.hit(i1);
t1.hit(t2);
return 0;
}
Пояснения по коду: взаимодействующие классы надобно определить от одного общего предка, коли они уж плавают и могут друг об друга биться, так и запишем - все варианты взаимодействия должны быть чистыми виртуальными функциями.
В общем, количество действительных реализаций функций уменьшается как раз на количество совпадающих. Не так уж и плохо.
Есть еще способы уменьшить их количество, основанные на преобразованиях классов - неявных или через конструкторы. Я правда не знаю, что раньше может запутать - количество диспетчерских функций или неявные преобразования; тут, пожалуй, можно только порадоваться появлению в стандарте ограничивающего модификатора explicit, который подавляет неявные вызовы конструкторов.
Увы, двойная диспетчеризация в C++ всегда громоздкая и неудобная вещь, и вряд ли будет другой. Если мы добавляем новые классы в диспетчеризацию, приходится переписывать ранее написанные классы; все классы имеют доступ к функциям друг друга или функции должны быть открытыми.
Это - плата за отсутствие в C++ функций, виртуальных по отношению к 2 и более классам.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Диспетчеризация и реальный мир
Диспетчеризация и реальный мир До настоящего момента мы обсуждали дисциплины диспетчеризации и состояния потоков, но практически ничего не сказали относительно того, почему и когда происходит собственно перепланирование. Существует распространенное заблуждение, что
Спорадическая диспетчеризация
Спорадическая диспетчеризация Системы реального времени принципиально отличаются от систем общего назначения тем, что для таких систем важна не только корректность выполнения возложенных на них функций, но и время, за которое эти функции реализуются. Можно даже
Совет 59: Двойная защита денег
Совет 59: Двойная защита денег При неблагоприятном для вас стечении обстоятельств умелый хакер сможет украсть почти любой пароль. Так что если важный для вас сервис предлагает двухфакторную аутентификацию, лучше согласиться. Дополнительный уровень защиты в виде,
Двойная жизнь технологий
Двойная жизнь технологий Современная технология отказывается вести себя так, как задумывали ее творцы, и принимает на себя неожиданные функции и роли. Дэвид Ноубл, плодовитый историк современных технологий, отстаивает эту точку зрения в своей книге “Производительные
Диспетчеризация задач в AS/400
Диспетчеризация задач в AS/400 С каждой задачей AS/400 связан блок управления в памяти, который называется элементом диспетчеризации задач TDE (task dispatching element). TDE — это фундаментальная структура данных, лежащая в основе управления задачами. Структура TDE не видима над MI, так как
ГЛАВА 8. ДИСПЕТЧЕРИЗАЦИЯ ПРОЦЕССОВ И ЕЕ ВРЕМЕННЫЕ ХАРАКТЕРИСТИКИ
ГЛАВА 8. ДИСПЕТЧЕРИЗАЦИЯ ПРОЦЕССОВ И ЕЕ ВРЕМЕННЫЕ ХАРАКТЕРИСТИКИ В системе разделения времени ядро предоставляет процессу ресурсы центрального процессора (ЦП) на интервал времени, называемый квантом, по истечении которого выгружает этот процесс и запускает другой,
Двойная буферизация
Двойная буферизация Двойная буферизация является методом программирования графического пользовательского интерфейса, при котором изображение виджета формируется вне экрана в виде пиксельной карты, и затем эта пиксельная карта выводится на экран. В ранних версиях Qt
* Продолжение следует??
* Продолжение следует?? - Даже не знаю, что тебе ответить. Предыдущий текст я писал примерно год назад, затем запал спал, появились новые задачи, то да сё, сам понимаешь.* Не отбрешешься!- Да, помнится, были задумки, но чтобы продолжить надо опять сосредоточится в нужное
Продолжение объекта
Продолжение объекта Snap to Extension – привязка к продолжениям объектов.Она необходима в том случае, когда при построении объектов требуется использовать линии, являющиеся временным продолжением существующих линий и дуг. Данный режим можно совмещать с режимом Apparent Intersect с
Продолжение объекта
Продолжение объекта Snap to Extension – привязка к продолжениям объектов.Она необходима в том случае, когда при построении объектов требуется использовать линии, являющиеся временным продолжением существующих линий и дуг. Данный режим можно совмещать с режимом Apparent Intersect с
Продолжение изменений
Продолжение изменений На данном этапе продолжение процесса управления изменениями в основном направлено на улучшение эффективности и производительности системы SAP, что может включать в себя следующие мероприятия:• Продолжение обучения персонала• Мониторинг
Продолжение просмотра
Продолжение просмотра Чтобы глубоко понять концепции, предпочтительно читать эту книгу последовательно, однако читатели, желающие дополнить данный теоретический обзор, могут, прежде чем идти дальше, посмотреть, как работает метод на практическом примере. Для этого
Двойная презентация: iPad 2 и Стив Джобс Михаил Карпов
Двойная презентация: iPad 2 и Стив Джобс Михаил Карпов Опубликовано 02 марта 2011 года Причины для беспокойства были — в январе Джобс объявил об очередном отпуске по состоянию здоровья, его видели выходящим из клиники по лечению рака и никто не был