在C ++中使用访问者模式作为解释器

时间:2010-01-15 20:07:41

标签: c++ design-patterns

我在使用C ++中的解释器访问模式时遇到了问题。以下代码根据需要生成(+)而不是((1 + 2)+3):

class ExpVisitor{
public:
    virtual void visit(class Add*)=0;
    virtual void visit(class Int*)=0;
};

class Exp{
public:
    virtual void accept(ExpVisitor *v){};
};

class Add : public Exp{
public:
    Exp e1,e2;
    Add(Exp in1,Exp in2){
        e1=in1;
        e2=in2;
    }
    void accept(ExpVisitor *v){
        v->visit(this);
    }
};

class Int : public Exp{
public:
    int val;
    Int(int v){
        val=v;
    }
    void accept(ExpVisitor *v){
        v->visit(this);
    }
};

class PrintExp : public ExpVisitor{
public:
    void visit(Add *e){
        cout  << '(';
        (e->e1).accept(this);
        cout << '+';
        (e->e2).accept(this);
        cout << ')';
    }
    void visit(Int *e){
        cout << e->val;
    }
};


int main(){
    Add e=Add(Add(Int(1),Int(2)),Int(3));
    PrintExp p;
    e.accept(&p);
    cout << endl;
}

问题当然是调用Exp :: accept而不是Add或Int。但是,由于Add拥有两个类型为Exp的成员e1和e2,因此我无法接受纯虚拟。我该如何修复这个例子?

3 个答案:

答案 0 :(得分:3)

您需要在添加Exp实例的指针中创建字段。然后,您可以将accept方法设为虚拟。当然,你必须管理内存。最简单的方法是使用智能ptrs。

答案 1 :(得分:0)

Add(Exp in1,Exp in2)还有一个问题 - 在1中,in2应该是引用或指针(除了MPG所说的)

答案 2 :(得分:0)

感谢您的帮助。作为参考,工作代码是

#include<iostream>
using namespace std;

class ExpVisitor{
public:
    virtual void visit(class Add*)=0;
    virtual void visit(class Int*)=0;
};

class Exp{
public:
    virtual void accept(ExpVisitor *v)=0;
};

class Add : public Exp{
public:
    Exp *e1,*e2;
    Add(Exp *in1,Exp *in2){
        e1=in1;
        e2=in2;
    }
    void accept(ExpVisitor *v){
        v->visit(this);
    }
};

class Int : public Exp{
public:
    int val;
    Int(int v){
        val=v;
    }
    void accept(ExpVisitor *v){
        v->visit(this);
    }
};

class PrintExp : public ExpVisitor{
public:
    void visit(Add *e){
        cout  << '(';
        (e->e1)->accept(this);
        cout << '+';
        (e->e2)->accept(this);
        cout << ')';
    }
    void visit(Int *e){
        cout << e->val;
    }
};

int main(){
    Exp *i1=new Int(1);
    Exp *i2=new Int(2);
    Exp *i3=new Int(3);
    Exp *e1=new Add(i1,i2);
    Exp *e2=new Add(e1,i3);

    PrintExp p;
    e2->accept(&p);
    cout << endl;

    delete i1,i2,i3,e1,e2;
}