Object-oriented has three elements:
Data abstraction, inheritance, and dynamic binding
Problem description:
1. An Expression Tree contains nodes that represent constants, unary operators, and binary operators.
2. We hope to create this tree by calling appropriate functions, and then print the complete brackets of this tree.
Object-oriented solutions:
We can use a union to hold specific values, use a list to represent child nodes, and use classes containing union and list to represent nodes. These classes have one thing in common: each class stores a value and some sub-nodes. Of course, there are also many differences, such as the type of the values they store, the number of sub-nodes, inheritance can capture these commonalities, while dynamic binding helps each node know its identity.
Further analysis shows that the tree has three nodes:
1. Integer expression, no subnode
2. contains a mona1 expression with a subnode.
3. contains a Binary Expression with two subnodes.
We need a class to represent the "concept" of a node, but this class does not represent a specific node. We will name this public base class as expr_node:
Class expr_node
{
// Youyuan function, which is used to output the <Operator
Friend ostream operator <(ostream &, const expr_node &)
{
}
Protected:
Virtual void print (ostream &) const = 0;
Virtual ~ Expr_node (){};
}
Because all objects to be created are derived from expr_node, virtual destructor are provided. Dynamic binding is only used for member functions, so we define a virtual function print. If you want to use the output operator instead of the print function, set print to protected and operator <to youyuan.
From the print statement of the function, we can see that it is a pure virtual function, which makes expr_node an abstract base class. This reflects our intention: There is no so-called expr_node object. The expr_node class only exists to obtain public interfaces.
Output OPERATOR:
Ostream & oprator <(ostream & O, const expr_node E)
{
E. Print (O );
Return O;
}
The following defines a specific class:
1. Integer: node class without subnodes
Class int_node: Public expr_node {
Friend class expr;
Int N;
Int_node (int K): n (k ){}
Void print (ostream & O) const {o <n ;}
}
2. mona1 Node
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 <")";}
}
3. Binary Node
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), opnd (B), opnd (c ){}
Void print (ostream & O) const
{O <"(" <* left <op <* Right <")";}
}
The constructor that creates a one-and Binary Expression is expected to get a pointer, so we can dynamically allocate nodes:
Binary_node * t = new binary_node ("*",
New unary_node ("-", new int_node (5 )),
New binary_node ("+", new int_node (3), new int_node (4 )));
Obviously, there is a problem here. We no longer have pointers to internal new objects. The next section describes how to create a new object and delete an object.