Design Pattern (2) combination pattern Composite (expression evaluate)

Source: Internet
Author: User

Design Pattern (2) combination pattern Composite (expression evaluate)

Purpose of the combination mode: Combine objects into a tree structure to represent the relationship between the entire part. Composite makes the use of a single object and a combination object consistent.

Disclosure: This example is a typical application of the combination mode. It is said that a compiler development team has used two and a half months to evaluate the expression, it was implemented by the author with over a dozen lines of code.

Requirement: expression evaluation is an important component of the compiler. In this example, there should be not much actual code, this is because I personally typed it out based on the examples in "C ++ meditation" (of course, it is the author's credit ). The purpose is to support a variety of unary operations, binary operations, and even more operations are added to the expression evaluate, the program is easy to expand, easy to use.


Code display: To tell the truth, this example is not very easy to understand, especially for beginners, because it is abstract, but if you first give how to use this result, it is easier to see why this organization is necessary. After a period of time, the author will forget how to implement it. Therefore, we will present it in a centralized manner to facilitate future memories.


The first is the main function.

From the main function, you can see what kind of things the author intends to create, at least what things the author wants to accomplish, and then you can guess what preparations you need to make to complete the things.

# Include "ExpressNode. h "# include" ValueNode. h "# include" UnaryNode. h "# include" BinaryNode. h "# include" Express. h "void main () {Express t = Express (3); t = Express ('+', t, 12); cout <
 
  
Running result:

Authorization + authorization/authorization + authorization/KvcDgyse/authorization + vP89OmuMPKx8/Cw + a1xNH519M8L3A + authorization + CjwvcD4KPHA + authorization = "brush: java; "> # pragma once # include" ExpressNode. h "# include Using namespace std; class Express {public: Express (int); // ValueNode (int) Express (3) Express (char, const Express); // UnaryNode (char, int) express ('+', t, 12) Express (char, const Express, const Express); // BinaryNode (char, int, int) Express ('+', 3,4) express (const Express &); Express & operator = (const Express &);~ Express (void); friend ostream & operator <(ostream & OS, const Express & e) {OS <* (e. p); return OS;} int eval () const; private: class ExpressNode * p; // The specific functions are implemented by this class, which derives from various expressions };


Express. cpp

#include "Express.h"#include "ValueNode.h"#include "UnaryNode.h"#include "BinaryNode.h"Express::Express(int a){p=new ValueNode(a);}Express::Express(char c, const Express e){p=new UnaryNode(c,e);}Express::Express(char c,const Express el,const Express er)//BinaryNode(char,int,int){p=new BinaryNode(c,el,er);}Express::Express(const Express& e1){p=e1.p;p->setUse(p->getUse()+1);}Express& Express::operator=(const Express& e1){(e1.p)->setUse((e1.p)->getUse()+1);p->setUse(p->getUse()-1);if(p->getUse()==0)delete p;p=e1.p;return *this;}Express::~Express(void){p->setUse(p->getUse()-1);if(p->getUse()==0)delete p;}int Express::eval() const{return p->eval();}

From the Express interface, we can see that when creating an object, Express is handed over to a specific expression class, and the base class pointer is used for Polymorphism to achieve unified computing and unified output expression.


The following is the base class of various expressions: ExpressNode. This class is the general form of all expressions. the interfaces of this class require the implementation of various expressions.


ExpressNode. h

# Pragma once # include
 
  
Using namespace std; class ExpressNode {public: friend class Express; int getUse (void) const; void setUse (int); friend ostream & operator <(ostream & OS, const ExpressNode & ExprNode) // (1) Output expression itself {ExprNode. print (OS); return OS;} ExpressNode (void): use (1) {} virtual ~ ExpressNode (void); protected: virtual void print (ostream & OS) const = 0; virtual int eval () const = 0; // (2) calculation expression value private: int use ;};
 


ExpressNode. cpp


#include "ExpressNode.h"ExpressNode::~ExpressNode(void){}int ExpressNode::getUse() const{return use;}void ExpressNode::setUse(int use1){use=use1;}
This class does not seem to have done anything, but provides a consistent interface for sub-classes to implement, the only integer variable to save the reference count, so that the expression does not copy and copy a lot.


The following describes the implementation of various expression subclasses: Value expression ValueNode (representing a numerical constant) and UnaryNode (positive and negative calculation) binary Expression BinaryNode (two expressions for phase operation +-*/addition, subtraction, multiplication, division)

ValueNode. h

#pragma once#include "ExpressNode.h"#include "Express.h"class ValueNode :public ExpressNode{public:friend class Express;ValueNode(void);ValueNode(int value1);~ValueNode(void);private:void print(ostream& os) const;int eval() const {return value;}int value;};

Evaluate the value of a numeric expression as the saved value


ValueNode. cpp

# Include "ValueNode. h" ValueNode: ValueNode (void) {} ValueNode: ValueNode (int value1): value (value1) {} ValueNode ::~ ValueNode (void) {} void ValueNode: print (std: ostream & OS) const {OS <
 
  
Output A value expression is to output the saved value.
  

UnaryNode. h

#pragma once#include "Express.h"#include "ExpressNode.h"class UnaryNode :public ExpressNode{public:friend class Express;UnaryNode(void);UnaryNode(char c,class Express left1);~UnaryNode(void);private:void print(ostream& os) const;int eval() const ;char opend;class Express left;};
It can be seen from this that the foundation of positive and negative operations is a general expression, any complex expression can be added with positive and negative operations.

UnaryNode. cpp

# Include "Express. h "# include" UnaryNode. h "UnaryNode: UnaryNode (char c, class Express left1): opend (c), left (left1) {} UnaryNode ::~ UnaryNode (void) {} void UnaryNode: print (std: ostream & OS) const {OS <"(" <
   
    

BinaryNode. h

#pragma once#include "ExpressNode.h"#include "Express.h"class BinaryNode :public ExpressNode{public:friend class Express;BinaryNode(void);BinaryNode(char,class Express,class Express);~BinaryNode(void);private:void print(ostream&) const;int eval() const;char opend;class Express left;class Express right;};
From this we can see that a Binary Expression is an operator, two general expressions. The specific work is still to be distributed, and only the operator is required. The output is also delegated down.

BinaryNode. cpp

# Include "BinaryNode. h "BinaryNode: BinaryNode (char c, class Express left1, class Express right1): opend (c), left (left1), right (right1) {} BinaryNode ::~ BinaryNode (void) {} void BinaryNode: print (ostream & OS) const {OS <"(" <
     
      
All the final evaluate operations will fall into the head of a numerical expression. The output process is a process of outputting the final summary from the bottom up on the tree.


This example can be said to be a typical application of the combination mode. It is said that a compiler development team has spent two and a half months to evaluate the expression, it was implemented by the author with over a dozen lines of code.














Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.