Loki库里的Acyclic Visitor

本文介绍了一种改进的访问者模式实现——Acyclic类库化。通过定义BaseVisitor和BaseVisitable基类,并利用模板和动态转换,使得访问者模式更加灵活且易于使用。文章详细解释了如何自定义Visit方法及如何使用户类成为可被访问的对象。

已经知道,使用 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的行为。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值