在c++沉思录举了一个表达式树的例子,将例如(-5)*(3+4)的式子表示成树的形式。可以通过如下形式:
Expr t = Expr("*", Expr("-", 5), Expr("+", 3, 4)); cout<<t<<" = "<<t.eval()<<endl;
创建树并将树打印出来。
这个程序主要用于理解动态绑定和句柄,程序实现代码如下:
#include <iostream>
#include <string>
/*
所有节点类型的父类
*/
class Expr_node{
// friend ostream& operator<<(ostream&, const Expr&);
friend class Expr;
int use;
protected:
Expr_node():use(1){}
virtual int eval()const = 0;
public:
virtual void print(ostream &)const = 0;//书中这个方法是protected修饰的,但是放在那里会报错
virtual ~Expr_node(){}
};
/**
句柄类
*/
class Expr{
//重载操作符
friend ostream& operator<<(ostream&, const Expr&);
Expr_node * p;
public:
Expr(int);
Expr(const string &, Expr);
Expr(const string &, Expr, Expr);
Expr(const Expr&t){ p = t.p; ++p->use; };
Expr & operator=(const Expr &);
~Expr(){if(--p->use==0)delete p;}
int eval()const {return p->eval();}
//ostream& operator<<(ostream&, const Expr&)const;
};
class Int_node: public Expr_node{
friend class Expr;
int n;
Int_node(int k):n(k){}
void print(ostream &o)const{o<<n;}
int eval()const{return n;}
};
class Unary_node:public Expr_node{
friend class Expr;
string op;
Expr opnd;
Unary_node(const string a, Expr b):op(a),opnd(b){}
void print(ostream& o)const {o << "(" << op << opnd << ")";}
int eval()const;
};
int
Unary_node::eval()const
{
if(op == "-")
return -opnd.eval();
throw "error,bad op " + op + "in unarnode";
}
class Binary_node: public Expr_node{
friend class Expr;
string op;
Expr left;
Expr right;
Binary_node(const string &a, Expr b, Expr c):
op(a), left(b), right(c){}
int eval()const;
void print(ostream& o)const
{
o << "(" << left << op << right<< ")";
}
};
int
Binary_node::eval()const
{
int op1 = left.eval();
int op2 = right.eval();
if(op == "-") return op1 - op2;
if(op == "+") return op1 + op2;
if(op == "*") return op1 * op2;
if(op =="/" && op2 != 0) return op1 / op2;
throw "error, bad op " + op + "in binarynode" ;
}
Expr::Expr(int n)
{
p = new Int_node(n);
}
Expr::Expr(const string &op, Expr t)
{
p = new Unary_node(op, t);
}
Expr::Expr(const string &op, Expr left, Expr right)
{
p = new Binary_node(op, left, right);
}
Expr&
Expr::operator=(const Expr& rhs)
{
rhs.p->use++;
if(--p->use == 0)
delete p;
p = rhs.p;
return *this;
}
ostream&
operator<<(ostream& o, const Expr& t)
{
t.p->print(o);
return o;
}
int main()
{
Expr t = Expr("*", Expr("-", 5), Expr("+", 3, 4));
cout<<t<<" = "<<t.eval()<<endl;
}