一个问题,如下图,没有画出箭头
*
- +
5 3 4
Class Expr_node{
friend ostream operate<<(ostream&,const Expr_node&); //<<符号是不能用动态绑定的,所以用print函数采用动态绑定,用<<符号调用print函数
//而且由于不准备提供print函数给用户使用,则把print定为protected,把<<符号定为友元。
protected:
virtual void print(ostream&) const = 0;
virtual ~Expr_node(){};
}
从Expr_node中派生出Int_node,Unary_node,Binary_node
class Int_node: public Expr_node{
friend class Expr;
int n;
Int_node(int k):n(k){}
Void print(ostream& o) const {o<<n;}
}
class Unary_node: public Expr_node{
friend class Expr;
String op;
Expr_node* opnd;
Unary_node(const String& a,Expr_node* b):op(a),opnd(b){}
Void print(ostream& o) const {o<<"(" << op << *opnd << ")";}
}
class Binary_node: public Expr_node{
friend class Expr;
String op;
Expr_node* left;
Expr_node* right;
Binary_node(const String& a,Expr_node* b,Expr_node* c):op(a),left(b),right(c){}
Void print(ostream& o) const {o<<"("<<*left << op << *right << ")";}
}
这样用户必须自己去维护那些指针分配的内存。这里没有对图中的箭头进行建模,而是把箭头作为一个简单的指针,然后还强迫
用户亲自操作这些指针。
所以我们另外定义个Expr这个句柄类来表示箭头。并用这个结构来代表一个树或子树,隐藏Expr_node节点。
class Expr{
friend ostream operate<<(ostream&,const Expr&);
Expr_node* p;
public:
Expr(int); //创建一个Int_node
Expr(const String&,Expr); //创建一个Unary_node
Expr(const String&,Expr,Expr); //创建一个Binary_node
Expr(const Expr&);
Expr& operate=(const Expr&);
~Expr(){delete p;}
}
考虑复制构造函数和赋值操作符,中要copy Expr_node指针,这里也涉及内存的问题,但最好还是不要真正实现复制操作了,仅copy指针
然后在Expr_node中增加一个计数:int use,初始化为1
Expr(const Expr& t){
p = t.p;
++p->use;
}
Expr& operate=(const Expr& rhs){
rhs.p->use++;
if(--p->use == 0)
delete p;
p = rhs.p;
return *this;
}
ostream operate<<(ostream& o,const Expr& t){
t.p->print(o);
return o;
}
然后修改各个派生自Expr_node的类,令其操作为私有的,将Expr类声明为友元,存储Expr,而不是存储指向Expr_node的指针。例如Binary_node
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 << ")";}
}
现在这种设计就非常好了,如果再增加一个功能,如计算运算结果,则只要在每个节点类中增加一个eval函数就可以了。
如果要再增加一个运算符,如类似?:(if then else),那么只要增加一个派生Expr_node的子类Ternary_node类就好了。
分享到:
相关推荐
《C++沉思录》--十年编程生涯的真知灼见
随着面向对象程序设计思 想的日益普及,很多支持面向 对象程序设计方法语言也相继 出现了,C++就是这样一种语 言。C++是Bjarne Stroustrup 于1980年在AT&T的贝尔实验 室开发的一种语言。
2024届求职-C++后端-学习笔记-操作系统、计算机网络、C++语言+算法 2024届求职-C++后端-学习笔记-操作系统、计算机网络、C++语言+算法 2024届求职-C++后端-学习笔记-操作系统、计算机网络、C++语言+算法 2024届求职-...
数据结构与算法--面向对象的C++设计 数据结构与算法--面向对象的C++设计 数据结构与算法--面向对象的C++设计 数据结构与算法--面向对象的C++设计 数据结构与算法--面向对象的C++设计 数据结构与算法--面向对象的C++...
面向对象程序设计C++听课笔记,依据中山大学博士的视频讲授和浙大副教授的讲课记录。
C++笔记 --- 类与结构 博客园大牛
C++程序设计教程--面向对象分册(郑秋生)完整答案
C++学习笔记--函数指针 函数指针 程序运行期间。每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址(也称“入口地址”)。我们可以将函数入口地址赋给一个指针变量,使该指针变量...
c++马石安-面向对象程序设计-习题答案.zip
内容是C++面对对象的,目录大致来源于菜鸟文档的C++面向对象,笔记是参考各种文章以及菜鸟文档改编的,内容包含C++类和对象(类定义和对象定义,类成员函数,类访问修饰符,友元函数,内联函数,this指针,静态成员...
C++11学习笔记 - 字串数据类型 希望你觉得有用
《C++沉思录》第八章 “一个面向对象程序的范例”
c++面向对象程序设计_杜茂康_课后答案[1-6章]_
面向对象程序设计(C++)ch4---继承.ppt
C++面向对象程序设计-电子教案
面向对象程序设计将数据和操作封装在一起,程序是由一个个对象组成的,对象之间通过接口进行通信,能够较好地支持程序代码的复用。 2.面向对象程序设计语言有四个特征: ⑴ 抽象性 ---- 许多实体的共性产生类。 ⑵ ...
c++面向对象笔记