Использование шаблона посетителя для интерпретатора в C ++ - PullRequest
2 голосов
/ 15 января 2010

У меня проблемы с применением шаблона посетителя для интерпретатора в 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. Однако я не могу сделать accept чисто виртуальным, поскольку Add обладает двумя членами e1 и e2 типа Exp. Как я могу исправить этот пример?

Ответы [ 3 ]

3 голосов
/ 15 января 2010

Вам нужно сделать поля в Добавить указатели на экземпляры Exp. Затем вы можете сделать метод accept виртуальным. Конечно, вы должны управлять памятью. Простейшим было бы использовать умные ptrs.

0 голосов
/ 15 января 2010

Спасибо за помощь. Для справки, рабочий код

#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;
}
0 голосов
/ 15 января 2010

Есть еще одна проблема в Add (Exp in1, Exp in2) - in1, in2 должны быть ссылками или указателями (в дополнение к тому, что сказал MPG)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...