Этот посетитель шаблона действительно динамичный? - PullRequest
0 голосов
/ 08 февраля 2012

Я играл с различными методами, чтобы сделать шаблон Visitor в C ++ более динамичным, чтобы классы-братья не должны были знать друг о друге, и это позволяет позднее расширять иерархию посетителей. Я придумал этот пример, основанный на «Более эффективном C ++» Скотта Мейерса:

class Dummy
{
public:
   void collide(int& gameobject) { }
};

class DynVisitor
{
public:
  template<class Visitor=Dummy, class Arg=int>
  void visit(Arg& target)
  {
    Visitor* vis = dynamic_cast<Visitor*>(this);

    if(vis != nullptr)
    {
      vis->collide(target);
    }
    else
    {
      cerr<<"No implementation!"<<endl;
    }
  }

  virtual ~DynVisitor() { }
};

class GameObject
{
public:
  virtual ~GameObject() { }
  virtual void collide(GameObject& obj) 
  {
    cout<<"Default collide implementation"<<endl;
  }

  virtual void accept(DynVisitor* vis) = 0;
};

class AsteroidVisitor
{
public:
  virtual void collide(Asteroid& target) = 0;
  virtual ~AsteroidVisitor() = 0;
};

class Collider : public DynVisitor, public AsteroidVisitor
{
public:
  virtual void collide(Satellite& target) { cout<<"Satellite collision."<<endl; }
  virtual void collide(Spaceship& target) { cout<<"Spaceship collision."<<endl; }
  virtual void collide(Asteroid& target) { cout<<"Asteroid collision."<<endl; }
  virtual ~Collider() { }
};

class Asteroid : public GameObject
{
public:
  virtual void accept(DynVisitor* visitor)
  {
    visitor->visit<AsteroidVisitor, Asteroid>(*this);
  }
};

int main(int argc, char** argv)
{
  DynVisitor* coll = new Collider();

  GameObject* ast = new Asteroid();

  ast->accept(coll);

  delete ast;

  delete coll;

  return 0;
};

Похоже, это работает, как и следовало ожидать, распечатывая «Столкновение астероидов», когда переданный GameObject является астероидом, и я могу добавить классы в иерархию, просто определив новый ABC с помощью метода collide () и расширив DynVisitor.

У меня вопрос: когда я добавляю новый класс в иерархию, нужно ли перекомпилировать DynVisitor?

РЕДАКТИРОВАТЬ: Добавлен класс астероидов ... извините за это.

1 Ответ

0 голосов
/ 08 февраля 2012

Все объекты могут сталкиваться друг с другом, поэтому они все равно должны быть посетителями друг друга, и, следовательно, нет никакого добавленного «динамизма».DynVisitor - это шаблон, поэтому он должен быть в модуле перевода и будет перекомпилироваться каждый раз.Фактически, в этом примере DynVisitor не дает никаких преимуществ, потому что функция accept () может вызывать функцию collide () вместо функции шаблона visit ().

...