我一直在使用各种方法使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?
编辑:添加了小行星类...抱歉。答案 0 :(得分:0)
所有物体都可能相互碰撞,因此它们仍然需要成为彼此的访客,因此没有增加“活力”。 DynVisitor是一个模板,因此需要在翻译单元中,并且每次都会重新编译。事实上,在这个例子中,DynVisitor没有任何好处,因为accept()函数可以调用collide()函数而不是模板visit()函数。