1.最近幾天在看c++ 沉思錄。裏面舉的例子確實讓我茅塞頓開,醍醐灌頂哈。node
2.我把代碼貼上去吧。根據原書的代碼敲的。ios
這一章的內容要解決的是如何表示一個表達式樹。c++
做者將全部類型的表達式都隔離開了,就用一個類來提供全部的接口,管理內存。讓用戶避免記住麻煩的用法和內存管理。this
至關巧妙spa
//Expr_node.h #include <iostream> using namespace std; class Expr; class Expr_node { friend ostream& operator<<(ostream& o, const Expr& t); friend ostream& operator<<(ostream& o, const Expr_node& e) { e.print(o); return o; } friend class Expr; int use; protected: Expr_node() : use(1) { } virtual void print(ostream& ) const = 0; virtual int eval() const = 0; virtual ~Expr_node() {} }; class Expr { friend ostream& operator<<(ostream&, const Expr&); friend class Expr_node; Expr_node* p; public: Expr(int); // create a int_node; Expr(const string &, Expr); Expr(const string &, Expr, Expr); Expr(const string& , Expr, 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();} }; class Int_node: public Expr_node { friend class Expr; int n; Int_node(int k):n(k) {} void print(ostream& o) const { o << n;} virtual int eval() const { return n;} }; //unary node 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; }; 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) {} void print(ostream& o) const { o << "( " <<left << op << right <<") "; } int eval() const; }; class Ternary_node : public Expr_node { friend class Expr; string op; Expr left; Expr middle; Expr right; Ternary_node(const string& a, Expr b, Expr c, Expr d): op(a), left(b), middle(c), right(d) { } void print(ostream& o) const; int eval( ) const; };
//Expr_node.cpp #include "Expr_node.h" 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::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 Unary_node::eval() const { if (op == "-") return -opnd.eval(); throw "error, bad op " + op + " int UnaryNode"; } 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"; } void Ternary_node::print(ostream& o) const { o<<"( "<<left<<" ? "<<middle<<" : "<<right<<") "; } int Ternary_node::eval() const { if (left.eval()) return middle.eval(); else return right.eval(); }
//main.cpp #include <iostream> #include "Expr_node.h" using namespace std; int main(int argc, char const *argv[]) { Expr t = Expr("*", Expr("-", 5), Expr("+", 3,4)); cout<<t<<" = "<< t.eval() <<endl; t = Expr("*", t, t); cout<<t<<" = "<< t.eval() <<endl; return 0; }