这个模板访客真的很动态吗?

时间:2012-02-08 04:26:23

标签: c++ templates visitor

我一直在使用各种方法使C ++中的访问者模式更具动态性,这样兄弟类就不必彼此了解,并允许以后扩展访问者层次结构。我想出了这个基于Scott Meyers的“更有效的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传递的是小行星时打印出“小行星碰撞”,我可以通过使用collide()方法定义新的ABC并扩展DynVisitor来向层次结构添加类。

我的问题是,当我向层次结构添加新类时,是否需要重新编译DynVisitor?

编辑:添加了小行星类...抱歉。

1 个答案:

答案 0 :(得分:0)

所有物体都可能相互碰撞,因此它们仍然需要成为彼此的访客,因此没有增加“活力”。 DynVisitor是一个模板,因此需要在翻译单元中,并且每次都会重新编译。事实上,在这个例子中,DynVisitor没有任何好处,因为accept()函数可以调用collide()函数而不是模板visit()函数。