访客模式和常量

时间:2014-09-14 10:46:02

标签: c++ const visitor

我遇到了有关访客模式和常量的问题。

假设在C ++中为小型游戏实现访问者模式实现,您可以在屏幕上绘制内容(取决于可绘制对象的内部状态),同时运行可以改变其内部状态的逻辑(非常多)任何你能想象到的游戏)。请原谅代码中的任何错误,因为这是在运行中完成的。

//Forward declaration of classes and visitor...

//class Game_actor; This one will be abstract, virtual, whatever.
class Game_actor_item;
class Game_actor_player;
class Game_actor_invisible;

class Visitor
{
    public:
//  virtual void visit(Game_actor& r)=0;
    virtual void visit(Game_actor_player& r)=0;
    virtual void visit(Game_actor_item& r)=0;
    virtual void visit(Game_actor_invisible& r)=0;
};

然后,一些类似界面的基础知识:

//This one defines stuff that can be on the screen.

class Drawable
{
    public:
    virtual void draw(Screen&)=0;
};

//This one defines stuff that changes its state. Let's assume that do_logic 
//returns an integer that means something to the controller and can be 
//interpreted via a long list of "message_codes" (1=Add score, 2=Substract 
//score, 3=Something else...). Each actor will run its logic and return its 
//message, that will be stored and interpreted later. This is mostly crap, 
//I know, but makes for a quick example.

class Game_actor
{
    private:

    float x;
    float y;

    public:
    virtual int do_logic()=0;
    void accept_visitor(Visitor& v)=0;
};

接下来,我们的对象层次结构:项目和播放器派生自actor,它定义了部分内部状态。当然,它们可以被吸引到屏幕上。有一个特定的演员不会被绘制,因为它是不可见的并控制其他东西。

class Game_actor_item: public Drawable, public Game_actor
{
    //Lines and lines of code.
    virtual void draw(Screen& s) {/* [...] */}
    virtual int do_logic() {/* [...] */}
};

class Game_actor_player: public Drawable, public Game_actor
{
    //Lines and lines of code.
    virtual void draw(Screen& s) {/* [...] */}
    virtual int do_logic() {/* [...] */}
};

class Game_actor_invisible: public Game_actor
{
    //Lines and lines of code.
    virtual int do_logic() {/* [...] */}
};

最后,访客专业化。我们将定义两个访客,一个将收集所有可绘制的演员,另一个将发送消息给游戏控制器。将从中收集可绘制的演员 它的基类的向量

class Visitor_drawing:public Visitor
{
    private:
    std::vector<Drawable *> draw_all_these;

    public:
//  virtual void visit(Game_actor& r) 
    virtual void visit(Game_actor_player& r) {draw_all_these.push_back(&r);}
    virtual void visit(Game_actor_item& r) {draw_all_these.push_back(&r);}

    //This one won't be drawn.
    virtual void visit(Game_actor_invisible&) {}

    std::vector<Drawable *> get_me_the_drawables() {return draw_all_these;}
}

class Visitor_logic:public Visitor
{
    private:
    std::vector<int> messages;

    public:
//  virtual void visit(Game_actor& r) 
    virtual void visit(Game_actor_player& r) {messages.push_back(r.do_logic());}
    virtual void visit(Game_actor_item& r) {messages.push_back(r.do_logic());}
    virtual void visit(Game_actor_invisible&) {messages.push_back(r.do_logic());}

    std::vector<int> fetch_me_the_messages() {return messages;}
}

所以,这是我们的设置。它缺少“accept_visitor”方法,但我相信你会在这里得到这个想法。层次结构的每个最终分支都会使accept_visitor(访客&amp; v){v.visit(* this);}无效。

在循环的任何给定时间,我们收集可绘制的东西并运行逻辑:

std::vector<Game_actor*> actors;

while(loop)
{
    Visitor_drawing dw;
    Visitor_logic dl;
    for(Game_actor * g : actors)
    {
        dw.visit(g);
        dl.visit(g);
    }       

    std::vector<Drawable *> draw_these=dw.get_me_the_drawables();
    std::vector<int> messages=dl.fetch_me_the_messages();

    for(Drawable * d : draw_these) d->draw(screen);
    for(int * m : messages) interpret_message(m);
};

这就是我的问题:我真的想把我的对象保持在应有的位置。对此的一个必要条件是绘制它们永远不会改变它们的内部状态(例如,保存一个mutable int times_drawn),因此它们可以(并且应该(??))是const。做他们的逻辑可能会在每个给定的转弯处改变他们的状态(例如,在屏幕上移动它们)。

鉴于此特定设置,您将如何管理const和非const访问者?我已经尝试将基本访问者拆分为const和非const基类,以便它们执行

class Const_visitor
{
    virtual void visit(const Thing&)=0;
};

class Non_const_visitor
{
    virtual void visit(Thing&)=0;
};

class Visitor_drawing:public Const_visitor
{
    virtual void visit(const Thing&)=0;
};

class Visitor_logic:public Non_const_visitor
{
    virtual void visit(Thing&)=0;
};

但似乎我必须实现单独的“accept_visitor”方法,因为编译器不区分调用:

void accept_visitor_const(Const_visitor& v)=0;
void accept_visitor(Non_const_visitor& v)=0;

这会导致基本访问者类中的各种重复(基本上写两次,const和非const版本),然后在主循环中分离调用:不再有单个accept_visitor,你必须提前知道什么你期待的那种访客(副作用是它真的写着“我会接受这个承诺不改变我的内部的访客”,这有点可取)。

无论如何,我是否遗漏了其他任何不会彻底改变此设置的选项?这是一个合适且理想的选择吗?

一如既往,非常感谢。

0 个答案:

没有答案
相关问题