Что такое Единственная и Двойная Отправка?

я имею, записал шаблон "посетитель" следующим образом, но я не понимаю то, что является единственной и двойной отправкой. AFAIK, единственная отправка, вызывают метод на основе типа вызывающего абонента, где двойная отправка, вызывают метод на основе типа вызывающего абонента и типа аргумента.

Я предполагаю, что двойная отправка, происходят в иерархии единого класса, но почему класс посетителя имеет две иерархии классов, но это все еще рассмотрело как двойную отправку.

void floppyDisk::accept(equipmentVisitor* visitor)
{
 visitor->visitFloppyDisk(this);
}

void processor::accept(equipmentVisitor* visitor)
{
 visitor->visitProcessor(this);
}

void computer::accept(equipmentVisitor* visitor)
{
 BOOST_FOREACH(equipment* anEquip, cont)
 {
  anEquip->accept(visitor);
 }

 visitor->visitComputer(this);
}

void visitFloppyDisk(floppyDisk* );
void visitProcessor(processor* );
void visitComputer(computer* );

Объясните использование примера кода, который я обеспечил.

AFAIK, первая отправка, происходят на объекте, кто вызывает принятие, и вторая отправка, происходят на объекте, кто вызывает метод посещения.

Спасибо.

9
задан nicholas 16 July 2010 в 08:04
поделиться

2 ответа

Короче говоря, однократная отправка - это когда метод полиморфен по типу одного параметра (включая неявное this ). Двойная отправка - это полиморфизм по двум параметрам.

Типичным примером для первого является стандартный виртуальный метод, который полиморфен по типу содержащего объекта. А второй можно реализовать через паттерн Посетитель.

[update] Я предполагаю, что в вашем примере floppyDisk , процессор и компьютер каждый наследует от общего базового класса, который определяет accept как виртуальный метод. Точно так же методы visit * должны быть объявлены виртуальными в equipmentVisitor , у которого должны быть некоторые производные классы с различными реализациями visit * . [/ update]

Исходя из вышесказанного, accept полиморфен как на this , так и на equipmentVisitor . Дискета, процессор и компьютер имеют собственную реализацию accept , поэтому, когда посетитель вызывает accept , вызов отправляется в зависимости от типа вызываемого. Затем вызываемый вызывает метод посещения конкретного типа посетителя, и этот вызов отправляется на основе фактического типа посетителя.

Теоретически может быть тройная, учетверенная и т. Д. Диспетчеризация, хотя я никогда не видел, чтобы это реализовывалось на практике (на языках, которые не поддерживают двойную и более высокую диспетчеризацию по своей природе, то есть - я, кажется, помню, что Smalltalk делает ?).Двойная диспетчеризация с использованием Visitor в C ++ и подобных языках уже сама по себе ошеломляет, поэтому реализация тройной и более высокой диспетчеризации была бы слишком сложной для использования в реальных приложениях.

9
ответ дан 4 December 2019 в 13:44
поделиться

В вашем примере вам не хватает основ механизма: наследования и виртуальности. Предположим, что в дополнение к вашему коду используется следующая иерархия классов:

class equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor) = 0;
}

class floppyDisk : public equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor);
}

class processor : public equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor);
}

class computer : public equipmentVisited
{
  virtual void accept(equipmentVisitor* visitor);
}

class equipmentVisitor
{
  virtual void visitFloppyDisk(floppyDisk* );
  virtual void visitProcessor(processor* );
  virtual void visitComputer(computer* );
}

// Some additional classes inheriting from equipmentVisitor would be here

Теперь представьте, что у вас есть этот фрагмент кода в какой-то функции:

equipmentVisited* visited;
equipmentVisitor* visitor;
// ...
// Here you initialise visited and visitor in any convenient way
// ...
visited->accept(visitor);

Благодаря механизму двойной диспетчеризации эта последняя строка позволяет любому equipmentVisited принимать любой equipmentVisitor, независимо от их фактических статических типов. В конце концов, правильная функция будет вызвана для правильного класса.

Подведем итог:

  • Первая отправка вызывает accept() для соответствующего класса
  • Вторая диспетчерская вызывает соответствующую функцию для класса, выбранного первой отправкой
6
ответ дан 4 December 2019 в 13:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: