刚开始看沉思录,觉得太枯燥。到了第八章,作者关于面向对象问题的分析,我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;
}