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