此回是針對上回所設計方案的擴展,下面將會演示
(1)如何增加計算表達式的值的功能
(2)如何增加新的節點類型(已經有表示單個數、一元操作符、二元操作符的節點類型Int_node\Unary_node\Binary_node,將演示如何增加三元操作符(Ternary_node))
完整代碼如下:
#include <iostream>
#include <string>
using namespace std;
class Expr_node
{
friend class Expr; //友元類可以被繼承
int use; //引用計數
public:
virtual void print(ostream&) const = 0;
public:
Expr_node():use(1) {}
virtual ~Expr_node() {}
virtual int eval() const = 0;
};
class Expr //句柄類
{
friend ostream& operator<<(ostream &o, const Expr &e);
private:
Expr_node *p; //指向基類的指針
public:
Expr(int n);
Expr(const string &op, Expr t);
Expr(const string &op, Expr left, Expr right);
Expr(const string &op, Expr left, Expr middle, Expr right);
Expr(const Expr &t);
Expr& operator=(const Expr&);
~Expr()
{
if(--p->use == 0)
delete p;
}
int eval() const
{
return p->eval();
}
};
class Int_node: public Expr_node
{
private:
int n;
public:
Int_node(int k):n(k) {}
void print(ostream &o) const
{
o << n;
}
int eval() const { return n; }
};
class Unary_node: public Expr_node
{
private:
//friend class Expr;
string op;
Expr opnd;
public:
Unary_node(const string &a, Expr b):op(a), opnd(b) {}
void print(ostream &o) const
{
o << "(" << op << opnd << ")";
}
int eval() const
{
if(op == "-")
return -opnd.eval();
throw "error!錯誤的一元操作符";
}
};
class Binary_node: public Expr_node
{
private:
//friend class Expr;
string op;
Expr left;
Expr right;
public:
Binary_node(const string &a, Expr b, Expr c):op(a), left(b), right(c) {}
void print(ostream &o) const
{
o << "(" << left << op << right << ")";
}
int 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 == "/") return op1 / op2;
throw "error! 錯誤的二元操作符!";
}
};
class Ternary_node: public Expr_node
{
private:
string op;
Expr left;
Expr middle;
Expr right;
public:
Ternary_node(const string& a, Expr b, Expr c, Expr d):op(a), left(b), middle(c), right(d) {}
void print(ostream &o) const
{
o << "(" << left << "?" << middle << ":" << right << ")";
}
int eval() const
{
if(left.eval())
return middle.eval();
else
return right.eval();
}
};
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(const string &op, Expr left, Expr middle, Expr right) { p = new Ternary_node(op, left, middle, right); }
Expr::Expr(const Expr& t) { p = t.p; ++p->use; }
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 &e)
{
e.p->print(o);
return o;
}
void main()
{
Expr t = Expr("*",
Expr("-", Expr(5)),
Expr("+", Expr(3), Expr(4)));
cout << t << "=" << t.eval() << endl;
Expr t2 = Expr("-", Expr(5), Expr("?:", Expr(0), Expr(1), Expr(2)));
cout << t2 << "=" << t2.eval() << endl;
}
運行結果如下:
((-5)*(3+4))=-3
(5-(0?1:2))=3