C++沉思录第八章算数表达式树的面向对象问题的分析

刚开始看沉思录,觉得太枯燥。到了第八章,作者关于面向对象问题的分析,我follow书上的设计开发,理解了一些以前只是在书上看到的概念。
给自己做几点注解吧:
1.虚基类用来表达所有的继承类的共有特点,在这个例子中,所有的继承类都要有输出和求值计算,所以我们把这两个函数定义为虚函数。
2.虚基类必须至少含有一个纯虚函数。该纯虚函数可以定义也可以不定义。
3.我们要保证由虚基类派生出来的类的对象能被正确的析构,所以将虚基类的析构函数定义为虚函数。
4.对于虚函数如果没有定义,也应该使用一对{}来表明。
5.友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类中的隐藏信息(包括私有成员和保护成员),而且友元类应先定义在使用友元类的类的前面。
6.当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一类的友元类。
7.友元关系不可以被继承,也不可以传递,而且是单向的。
8.Expr的构造函数使用的参数为Expr,这样就可以嵌套构造Expr对象。

#ifndef EXPR_H
#define EXPR_H
#include<iostream>
#include<string>
using namespace std;

class Expr_node//抽象基类
{
	friend class Expr;
	int use;
	friend ostream & operator << (ostream &, const Expr_node &);
protected:
	Expr_node() :use(1){}
	virtual int eval()const=0;
	virtual ~Expr_node(){};
public:
	virtual void print(ostream &)const = 0;
};

class Expr//具体类
{
	friend class Expr_node;
	friend ostream& operator <<(ostream & o, const Expr &);
	Expr_node * p;
public:
	Expr(int);
	Expr(const string & op, Expr);
	Expr(const string &op, Expr, Expr);
	Expr(const string &op, 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; }
	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){}
	int eval()const;
	void print(ostream & o)const
	{	o << "(" << op << opnd << ")";	}
};

class Binary_node :public Expr_node
{
	friend class Expr;
	string op;
	Expr  left, right;
	Binary_node(const string & a, Expr  b, Expr  c)
		:op(a), left(b), right(c){}
	int eval()const;
	void print(ostream & o)const{ o << "(" << left << op << right << ")"; }
};

class Ternary_node :public Expr_node
{
	friend class Expr;
	string op;
	Expr left;
	Expr middle;
	Expr right;
	Ternary_node(const string & s, Expr l, Expr m, Expr r)
		:op(s), left(l), middle(m), right(r){}
	void print(ostream & o)const;
	int eval()const;
};

int Binary_node::eval()const
{
	int l = left.eval();
	int r = right.eval();

	if (op == "+")return l + r;
	if (op == "-")return l - r;
	if (op == "*")return l * r;
	if (op == "/"&&r!=0)return l / r;

	throw"error, bad op " + op + " int Binarynode";

}

int Unary_node::eval()const
{
	if (op == "-")return -opnd.eval();
	throw"error, bad op " + op + " int Unarynode";
}

Expr::Expr(int t)
{
	p = new Int_node(t);
}
Expr::Expr(const string & op, Expr e)
{
	p = new Unary_node(op, e);
}
Expr::Expr(const string &op, Expr d, Expr e)
{
	p = new Binary_node(op, d, e);
}
Expr::Expr(const string &op, Expr a, Expr b, Expr c)
{
	p = new Ternary_node(op, a, b, c);
}
Expr& Expr::operator=(const Expr &r)
{
	r.p->use++;
	if (--p->use == 0)delete p;
	p = r.p;
	return *this;
}

ostream & operator << (ostream &o, const Expr_node &t)
{
	t.print(o);
	return o;
}
ostream& operator <<(ostream & o, const Expr &r)
{
	r.p->print(o);
	return o;
}

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();
}
#endif



#include<iostream>
#include"EXPR.h"
using namespace std;
int main()
{
	Expr t = Expr("*", Expr("-", 5), Expr("+", 3, 4));
	cout << t <<"="<<t.eval()<< endl;
	//t = Expr("*", t, t);
	//cout << t << "=" << t.eval() << endl;
	Expr m = Expr("?",-1, 99,26);
	cout << m << "=" << m.eval() << endl; 
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值