Брутально и бессердечно о программировании и проектировании
ГлавнаяФорумПаттерныАнтипаттерныТест-драйвЗаметкиВопрос-ответКнигорецензииСправочная

22. Мультиметоды и диспетчеризация

Теория
Для начала напомню, что такое мультиметоды. Посмотрите на приведенный ниже код.
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>

struct shape
{
    virtual ~shape() {}
};

struct square   : public shape {};
struct triangle : public shape {};
struct sphere   : public shape {};

void foo(shape*, shape*)
{
    std::cout << "shape*, shape*" << std::endl;
}

void foo(triangle*, sphere*)
{
    std::cout << "triangle*, sphere*" << std::endl;
}

int main()
{
    shape* s1 = new triangle;
    shape* s2 = new sphere;

    foo(s1, s2);

    delete s2;
    delete s1;

    return 0;
}
В данном примере, конечно же, будет вызвана первая функция, так как выбор функции-кандидата происходит на этапе компиляции.
Мультиметоды можно назвать динамической перегрузкой. Посмотрите на приведенный фрагмент кода. Представьте себе, что вы хотите, чтобы выбор нужной функции, помимо существующих правил, также опирался на информацию о дочерних типах, скрытых за указателями или ссылками на базовые. При этом никаких требований к классам-участникам иерархии быть не должно.
Сам язык C++ напрямую не предоставляет возможности работать с мультиметодами. Поддержку мультиметодов приходится реализовывать самому, причем ни одного изящного решения этой задачи я пока не видел. Решение так или иначе сводится либо к последовательной проверки указателей-кандидатов через dynamic_cast, либо к составлению RTTI-словарей.
 
Code-driven vs data-driven
Мультиметоды заставляют писать код там, где довольно часто можно воспользоваться данными. Например, современные графические процессоры, позволяфющие зрителю любоваться фотореалистичной компьютерной графикой, по большому счету, умеют выполнять только одну операцию — «нарисовать треугольник». У видеокарты нет функций «нарисовать слона» или «нарисовать попугая». У нее есть всего одна функция — «нарисовать треугольник». А кто это будет, слон или попугай, определяется исключительно данными. Точно также у современных систем, рассчитывающих механику взаимодействия тел, нет функции «рассчитать столкновение автомобиля и фонарного столба». Есть всего одна функция — «рассчитать столкновение двух полигональных моделей». Логика работы таких подсистем до тупости проста, и это не случайно. Гораздо проще нарастить производительность железа, нежели сопровождать и развивать сложную динамическую логику обработки данных.
Если вы уже успели решить задачу о переводчиках, то вы, вероятно, согласитесь, что описывать индивидуальное решение для каждого уникального набора типов при большом количестве этих типов — задача не из приятных.
 
В итоге
Являются ли мультиметоды хорошим паттерном или нет — вопрос довольно спорный, и, на мой взгляд, каждый программист должен разрешить его для себя самостоятельно. Что же касается лично меня — я стараюсь избегать их использования.
Лично я вижу один очевидный случай, в котором необходима диспетчеризация — когда используемое внешнее API вынуждает вас на это. Возможно, что в каких-то особо специфических ситуациях мультиметоды будет оправданным, или даже единственно верным подходом, однако в большинстве случаев, на мой взгляд, существует более легкое и изящное решение.
Если вы решили использовать наследование — будьте бдительны. Если вы решили использовать мультиметоды — будьте бдительны в квадрате.

Оглавление
Статистика
© 2007—2009 Inside C++ Коммерческие услугиКонтактная информация

цены на пластические операции в магазине. кровля водосток Lindab металлочерепица. Идем на сайт spark ярославль - читем свежую информацию.