Читаем Идиомы и стили С++ полностью

В Шаге 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 и более классам.

<p>Шаг 15 - Как сделать массив из чего угодно.</p><p>Массивы и оператор operator[].</p>
Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных