An object-oriented program example
Three elements of object-oriented programming: data abstraction, inheritance, and dynamic binding. This routine shows these three elements completely.
The program needs to output the arithmetic expression tree: (-5) * (3 + 4)
Expressions header file:
# Ifndef expression_h_h # define expression_h_h # include <iostream> # include <string> using namespace STD; // base class exprnode {public: exprnode (): m_use (1) {} // when the subclass of exprnode executes its own constructor, the constructor of the parent class will be called // The constructor of the parent class in it will be used as the sub-class to reference the Count virtual void print (ostream &) const = 0; // virtual function, re-define in its subclass and dynamically bind virtual ~ during runtime ~ Exprnode () {}// ensure that the correct derived class destructor virtual int result () const = 0; private can be called when you delete an object directed by the exprnode * pointer: friend ostream & operator <(ostream & OS, const exprnode & RHs) // The output operator {RHS. print (OS); Return OS;} friend class expr; int m_use; // count}; // handle class expr {public: expr (INT ); // create an int object expr (const string &, expr); // create an unarynode object expr (const string &, expr, expr ); // create a bianrynode object expr (const string &, expr, ex PR, expr); // create a ternarynode object // copy constrollexpr (const expr & T); expr & operator = (const expr &);~ Expr () {If (-- m_penode-> m_use = 0) delete m_penode;} int result () const {return m_penode-> result ();} PRIVATE: friend ostream & operator <(ostream & OS, const expr & RHs) {RHS. m_penode-> Print (OS); Return OS;} // friend class exprnode; exprnode * m_penode;}; // derived class: Number node class intcode: Public exprnode {friend class expr; intcode (int K): m_ncount (k) {} void print (ostream & OS) const {OS <m_ncount;} int result () const {return m_ncount;} PRIVATE: int m_ncount; // value}; // derived class: single object operator class unarynode: Public exprnode {friend class expr; unarynode (const string & A, expr B): m_ustr (), m_pnode (B) {} void print (ostream & OS) const {OS <"(" <m_ustr <m_pnode <")";} int result () const; PRIVATE: String m_ustr; // single object operator expr m_pnode; // operand}; // derived class: binary operator class bianrynode: Public exprnode {friend class expr; bianrynode (const string &, expr B, expr C): m_bstr (A), m_bleft (B), m_bright (c) {} void print (ostream & OS) const {OS <"(" <m_bleft <m_bstr <m_bright <")" ;}int result () const; private: String m_bstr; // binocular operator expr m_bleft; // left operand expr m_bright; // right operand}; // derived class: ternarynode: Public exprnode {ternarynode (const string &, expr B, expr C, expr D): m_tstr (A), m_tleft (B), m_tmiddle (C), m_tright (d) {} void print (ostream & OS) const; int result () const; private: Friend class expr; string m_tstr; expr m_tleft; expr m_tmiddle; expr m_tright;}; # endif
Expressions implementation file:
# Include "expressions. H "// handle class implementation expr: expr (int n) {m_penode = new intcode (n);} expr: expr (const string & OP, expr T) {m_penode = new unarynode (OP, T);} expr: expr (const string & OP, expr left, expr right) {m_penode = new bianrynode (OP, left, right);} expr: expr (const string & OP, expr left, expr middle, expr right) {m_penode = new ternarynode (OP, left, middle, right );} expr: expr (const expr & T) {m_penode = T. m _ Penode; ++ m_penode-> m_use;} expr & expr: Operator = (const expr & RHs) {++ RHS. m_penode-> m_use; If (-- m_penode-> m_use = 0) delete m_penode; m_penode = RHS. m_penode; return * This;} // single object operator int unarynode: result () const {If (m_ustr = "-") Return-m_pnode.result (); throw "error, bad m_ustr "+ m_ustr +" in unarynode ";} // binary operator int bianrynode: result () const {int val1 = m_bleft.result (); int val2 = m_bright.result (); If (M_bstr = "-") return val1-val2; If (m_bstr = "+") return val1 + val2; If (m_bstr = "*") return val1 * val2; If (m_bstr = "/" & val2! = 0) return val1/val2; throw "error, bad m_bstr" + m_bstr + "in bianrynode";} // void ternarynode: Print (ostream & OS) const {OS <"(" <m_tleft <"? "<M_tmiddle <": "<m_tright <") ";} int ternarynode: result () const {If (m_tleft.result ()) {return m_tmiddle.result ();} else {return m_tright.result ();}}
Testdemo file:
#include "stdafx.h"#include "Expressions.h"int main(int argc, char* argv[]){Expr t = Expr("*", Expr("-", 5), Expr("+", 3, 4));cout<<t<<"="<<t.Result() <<endl;t = Expr("*", t, t); cout<<t<< "=" <<t.Result() <<endl;return 0;}
Summary:
When we analyze that the expression is composed of nodes and edges, we can design data abstraction to model the tree. Inheritance allows us to grasp the similarities between nodes and edges, dynamic binding helps us define operations for various types of nodes, so that the compiler can be responsible for arranging the correct function to be called at runtime. In this way, data abstraction and dynamic binding allow us to focus on every type of behavior and implementation without worrying about interaction with other objects.