关闭

Loki库里的Acyclic Visitor

661人阅读 评论(0) 收藏 举报

已经知道,使用 Visitor有这样那样的不便。Loki为了避免这些提供了两个方案,之一就是Acyclic的类库化。

class BaseVisitor
{
public:
    
virtual    ~BaseVisitor(){};
}
;

template    
<class T,typename R = void>
class Visitor
{
public:
    typedef    R    ReturnType;
    
virtual    ReturnType    Visit(T&)    = 0;
}
;

你的访问者必须继承这两个类,具体的情况可能是:

class MyVisitor
    :
public    BaseVisitor
    ,
public    Visitor<A>
    ,
public    Visitor<B>
{
public:
    
void    Visit(A&);    //visit A
    void    Visit(B&);    //visit B
}

使用起来很简单,记得继承和根据自己的特定类编写特定Visit方法就可以了。对于Visitable:

template    <typename    R = void>
class    BaseVisitable
{
public:
    typedef    R    ReturnType;
    
virtual    ~BaseVisitable(){};
    
virtual    ReturnType    Accept(BaseVisitor&)    = 0;
protected:
    template    
<class T>
    
static    ReturnType    AcceptImpl(T& visited,BaseVisitor& guest)
    
{
        
if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&guest))
        
{
            
return    p->Visit(visited);
        }

        
return    ReturnType();
    }

}
;

#define    DEFINE_VISITABLE()    
    
virtual    ReturnType    Accept(BaseVisitor& guest)    
    
{return    AcceptImpl(*this,guest);}

你已经猜到,你的Visitable必须继承BaseVisitable,但是,Visit是要动态转换的,这个调用地方必须在子类中,放在基类中动态转换没有任何意义。为了提供侵入用户类的方便手段,loki定义了DEFINE_VISITABLE()宏,如果你对MFC有一定了解的话,你一定会觉得这种手法很熟悉。

当然,侵入宏只是为了只是动态转换,如果你需要,自己写也没什么,你还可以获得应有的自由度。

这样,一般的使用BaseVisitable的方法是:

class A    :public    BaseVisitable<>
{
public:
    DEFINE_VISITABLE()
}
;

把宏替换为它的定义代码,修改Accept的实现就可以自定义AcceptImpl的行为。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:181593次
    • 积分:2942
    • 等级:
    • 排名:第12784名
    • 原创:113篇
    • 转载:3篇
    • 译文:0篇
    • 评论:28条
    文章分类