C++沉思录读书笔记(8章)-一个面向对象程序范例2

此回是针对上回所设计方案的扩展,下面将会演示

(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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值