1.最近几天在看c++ 沉思录。里面举的例子确实让我茅塞顿开,醍醐灌顶哈。
2.我把代码贴上去吧。根据原书的代码敲的。
这一章的内容要解决的是如何表示一个表达式树。
作者将所有类型的表达式都隔离开了,就用一个类来提供所有的接口,管理内存。让用户避免记住麻烦的用法和内存管理。
相当巧妙
//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;
}