面向对象编程有三个要素:数据抽象、继承以及动态绑定。
编译注意点:
函数ostream& operator<<(ostream&,const Expr&)要访问class Expr_node的print,但是print是protected的。
所以要把函数ostream& operator<<(ostream&,const Expr&)声明为class Expr_node的友元函数。
class Expr_node中的友元函数有Expr类参数,但是此时class Expr还没有声明。所以要在class Expr_node前加class Expr;
Expr类的以下三个成员函数,因为要创建class Int_node、class Unary_node、class Unary_node这三个类的对象,但此时这三个类还没有声明。
所以这三个函数的定义要放到class Int_node、class Unary_node、class Unary_node这三个类声明之后。
Expr(int);
Expr(const string&, Expr);
Expr(const string&, Expr, Expr);
#include <iostream>
#include <string>
using namespace std;
class Expr;
class Expr_node{
friend class Expr;
friend ostream& operator<<(ostream&,const Expr&);
int use;
protected:
Expr_node(): use(1) {}
virtual void print(ostream&) const = 0;
virtual ~Expr_node() {}
virtual int eval() const = 0;
};
class Expr{
friend class Expr_node;
friend ostream& operator<<(ostream&, const Expr&);
Expr_node* p;
public:
Expr(int);
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& rhs){
rhs.p->use++;
if(--p->use == 0)
delete p;
p = rhs.p;
return *this;
}
~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;}
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 {
if(op == "-")
return -opnd.eval();
throw "error, bad op" + op + "int UnaryNode";
}
};
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{
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 + "int BinaryNode";
}
};
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{
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); }
ostream& operator<<(ostream& o, const Expr& t)
{
t.p->print(o);
return o;
}
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;
//Expr k = Expr("?", t, Expr("-", 5), Expr("+", 3, 4));
//cout << k << endl;
return 0;
}
原文:https://www.cnblogs.com/vonyoven/p/11778297.html