views:

191

answers:

3

Hi, I'm having trouble applying the visitor pattern for an interpreter in C++. The following code produces (+) rather than ((1+2)+3) as desired:

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;
}

The problem, of course, is that Exp::accept is being called instead of than from Add or Int. However, I can't make accept purely virtual since Add possess two members e1 and e2 of type Exp. How can I fix this example?

+4  A: 

You need to make the fields in Add pointers to instances of Exp. Then you can make the accept method virtual. Of course you then have to manage the memory. The simplest would be to use smart ptrs.

MPG
A: 

There is one more problem in Add(Exp in1,Exp in2) - in1,in2 shoud be references or pointers (in addition to what MPG said)

a1ex07
A: 

Thanks for the help. For reference, the working code is

#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;
}
Anon