• No results found

534 534 + + _ *

N/A
N/A
Protected

Academic year: 2021

Share "534 534 + + _ *"

Copied!
8
0
0

Loading.... (view fulltext now)

Full text

(1)

Object-Oriented Design and Programming

C++ Advanced Examples with Inheritance and Dynamic Binding

Introduction

Expression Tree Diagram Expression Tree Behavior C Version

Memory Layout of C Version Print Tree Function

Limitations with C Approach OO Alternative

Relationships Between Trees and Nodes C++ Node Interface

C++ Tree Interface

C++ Int Node and Unar Node Interface1

C++ Binary Node Interface Memory Layout for C++ Version

C++ Int Node and Unary Node Implementations C++ Binary Node Implementation

C++ Tree Implementation C++ Main Program Expression Tree Diagram 1 Expression Tree Diagram 2

Extending Solution with Ternary Nodes C++ Ternary Node Implementation Di erences from C Implementation Summary

Introduction

 The following inheritance and dynamic bind-ing example constructs expression trees { Expression trees consist of nodes containing oper-

ators and operands

. Operators have di erent precedence levels and di erentarities,e.g.,

 Multiplication takes precedence over addition

 The multiplication operator has two arguments, whereas unary minus operator has only one

. Operands are integers, doubles, variables, etc.

 We'll just handle integers in the example:::

Expression Tree Diagram

+

5 3 4

*

BINARYNODES

+

5 3 4

INTEGER NODES UNARY

NODE

_

3

(2)

Expression Tree Behavior

 Expressiontrees

{ These trees may be \evaluated" via di erent traver- sals

. e.g., in-order, post-order, pre-order, level-order { The evaluation step may perform various operations:::,

e.g.,

. Traverse and print the expression tree

. Return the \value" of the expression tree

. Generate code

. Perform semantic analysis

4

C Version

 A typical functional method for implement-ing expression trees in C or Ada involves us-ing ature,e.g.struct, /unionto represent data struc-

typedef structTree Node Tree Node;

structTree Nodef enumf

NUM, UNARY, BINARY

gtag;

shortuse; /* reference count */

unionf intnum;

charop[2];

go;

#de nenum o.num

#de neop o.op unionf

Tree Node *unary;

structfTree Node *l, *r;gbinary;

gc;

#de neunary c.unary

#de nebinary c.binary

g;

5

Memory Layout of C Version

tag use

op

num

unary

binary

MEMORY LAYOUT

Tree Node

Tree Node

1 1|2

CLASS RELATIONSHIPS

 Here's what the memory layout of astruct Tree Node object looks like

Print Tree Function

 Typical C or Ada implementation (cont'd) { Use aswitch statement and a recursive function

to build and evaluate a tree,e.g.,

voidswitchcaseprint tree (Tree Node *root)NUM: cout(root->tag)<<froot->num;f break; caseUNARY:

cout<<"("<<root->op[0]; print tree (root->unary);

cout<<")";break; caseBINARY:

cout<<"(";

print tree (root->binary.l);

cout<<root->op[0]; print tree (root->binary.r);

cout<<")";break; default:

cerr<<"error, unknown type\n";

exit (1);

g

g

(3)

Limitations with C Approach

 Problems or limitations with the typical de-sign and implementation approach include { Language feature limitations in C and Ada

. e.g., no support for inheritance and dynamic bind- ing

{ Incomplete modeling of the problem domain that results in

1. Tight coupling between nodes and edges inunion representation

2. Complexity being in algorithms rather than the data structures

. e.g.,switchstatements are used to select be- tween various types of nodes in the expression trees

 compare with binary search!

. Data structures are \passive" in that functions do most processing work explicitly

8

Limitations with C Approach (cont'd)

 Problems with typical approach (cont'd) { The program organization makes it dicult to ex-

tend,e.g.,

. Any small changes will ripple through the entiredesign and implementation

 e.g., see the ternary extension below

. Easy to make mistakesswitching on type tags..

{ Solution wastes space by making worst-case as- sumptionswrtstructs andunions

. This not essential, but typically occurs

. Note that this problem becomes worse the bigger the size of the largest item becomes!

9

OO Alternative

 Contrast previous functional approach withan object-oriented decomposition for the sameproblem:

{ Start with OO modeling of the \expression tree"

problem domain:

. e.g., go back to original picture { There are several classes involved:

classNode: base class that describes expression tree vertices:

classconvertingInt Node: used for implicitlyintto Tree node

classUnary Node: handles unary operators,

e.g.,,10, +10, !a, or~foo, etc.

classBinary Node: handles binary operators,

e.g., a + b, 10 , 30, etc.

classTree: \glue" code that describes expression tree edges

{ Note, these classes model elements in the problem domain

. i.e., nodes and edges (or vertices and arcs)

Relationships Between Trees and Nodes

Tree

Node A

Int Node Unary

Binary Node Node

Ternary Node

1 1

1

1 1 2 1

3

11

(4)

C++ Node Interface

 // node.h

#ifndef NODE H

#de ne NODE H

#include<stream.h>

#include"tree.h"

/* Describes the Tree vertices */

classNodef friend classTree;

friendostream &operator<<(ostream &,constTree &);

protected: /* only visible to derived classes */

Node (void): use (1)fg // pure virtual

virtual voidprint (ostream &)const=0;

virtual~Node (void)fg; // important to make virtual!

private:

intuse; /* reference counter */

g;

#endif

12

C++ Tree Interface

 // tree.h

#ifndef TREE H

#de ne TREE H

#include"node.h"

/* Describes the Tree edges */

classTreef friend classNode;

friendostream &operator<<(ostream &,constTree &);

public: Tree (int);

Tree (constTree &t);

Tree (char*, Tree &);

Tree (char*, Tree &, Tree &);

void operator=(constTree &t);

virtual~Tree (void); // important to make virtual private:

Node *ptr; /* pointer to a rooted subtree */

g;

#endif

13

C++ Int Node and Unar Node Interface

 // int-node.h

#ifndef INT NODE H

#de ne INT NODE H

#include"node.h"

classInt Node :publicNodef friend classTree;

privateint:num; /* operand value */

publicInt Node (virtual void: intprint (ostream &stream)k); const;

g;#endif

 // unary-node.h

#ifndef UNARY NODE H

#de ne UNARY NODE H

#include"node.h"

classUnary Node :publicNodef friend classTree;

publicUnary Node (virtual void: print (ostream &stream)const char*op,constTree &t);const; privateconst charTree operand;: *operation;

g;#endif

C++ Binary Node Interface

 // binary-node.h

#ifndef BINARY NODE H

#de ne BINARY NODE H

#include"node.h"

classBinary Node : publicNodef friend classTree;

public:

Binary Node (const char*op,constTree &t1, constTree &t2);

virtual voidprint (ostream &s)const; privateconst char: *operation;

Tree left, right;

g;

#endif

(5)

Memory Layout for C++ Version

tag

op

vptr

use

Node PART

num

Node PART vptr

ptr

operator

operand (Tree PART)

Node PART

operator

left (Tree PART)

Node PART

operator

right (Tree PART)

left (Tree PART)

right (Tree PART)

middle (Tree PART)

tag

op

vptr

use Node

Node PART

num

Int_Node Node PART vptr

ptr

Tree operator

operand (Tree PART)

Unary Node Node PART

operator

left (Tree PART)

Binary Node

Node PART

operator

right (Tree PART)

left (Tree PART)

right (Tree PART)

middle (Tree PART)

Ternary Node

 Memory layouts for di erent subclasses of

Node

16

C++ Int Node and Unary Node Implementations

 // int-node.C

#include"int-node.h"

Int Node::Int Node (intk): num (k)fg voidInt Node::print (ostream &stream)constf

stream<<this->num;

g

 // unary-node.C

#include"unary-node.h"

Unary Node::Unary Node (const char*op,constTree &t1) : operation (op), operand (t1)fg

voidUnary Node::print (ostream &stream)constf stream<<"("<<this->operation<<" "

<<this->operand // recursive call!

<<")";

g

17

C++ Binary Node Implementation

 // binary-node.C

#include"binary-node.h"

Binary Node::Binary Node (const char*op,constTree &t1, constTree &t2):

operation (op), left (t1), right (t2)fg voidBinary Node::print (ostream &stream)constf

stream<<"("<<this->left // recursive call

<<" "<<this->operation

<<" "<<this->right // recursive call

<<")";

g

C++ Tree Implementation

 // tree.C

#include"tree.h"

#include"int-node.h"

#include"unary-node.h"

#include"binary-node.h"

#include"ternary-node.h"

Tree::Tree (intnum) ptr (newInt Node (num))

gTree::Tree (constTree &t): ptr (t.ptr)

f// Sharing, ref-counting..++this->ptr->use;g Tree::Tree (const char*op,constTree &t)

: ptr (newUnary Node (op, t))fg Tree::Tree (constconst charTree &t2):*op,constTree &t1,

: ptr (newBinary Node (op, t1, t2))fg Tree::~Tree (void)f// Ref-counting, garbage collection

if(--this->ptr->use<=0) delete this->ptr;

gvoidTree::operator=(constTree &t)f

++t.ptr->use;

if(--this->ptr->use==0) // order important delete this->ptr;

this->ptr=t.ptr;

g

(6)

C++ Main Program

 // main.C

#include<stream.h>

#include"tree.h"

ostream &operator<<(ostream &s,constTree &tree)f tree.ptr->print (s); /* Virtual call! */

// (*tree->ptr->vptr[1]) (tree->ptr, s);

returns;

g

intmain (const// Tree ("*", Tree ("-", Tree (5)),// Tree ("+", Tree (3), Tree (4)));voidTree t1)f Tree ("+", 3, 4));=Tree ("*", Tree ("-", 5),

/* prints ((,5) * (3 + 4)) */

cout<<t1<<"\n";

constTree t2=Tree ("*", t1, t1);

/* prints (((,5) * (3 + 4)) * ((,5) * (3 + 4))) */

cout<<t2<<"\n";

/* virtual destructor recursively deletesentire tree leaving scope */

g

20

Expression Tree Diagram 1

Binary Node

Unary Node

Int Node t1

5 3

4

-

*

+

print()

 Expression tree for t1= ((,5) * (3 + 4))

21

Expression Tree Diagram 2

Binary Node

Unary Node

Int Node t1

*

5 3

4

- +

print() t2

*

 Expression tree for t2= (t1 * t1)

Extending Solution with Ternary Nodes

 Extending the existing solution to supportternary nodes is very straight forward { i.e., just derived new class Ternary Node

classoperators,Ternary Node: handles ternarye.g., a==b ? c : d, etc.

 // ternary-node.h

#ifndef TERNARY NODE

#de ne TERNARY NODE

#include"node.h"

classTernary Node : publicNodef friend classTree;

privateconst charTree left, middle, right;: *operation;

publicTernary Node (virtual void: constprint (ostream &)const charTree &,const*,constconstTree &);Tree &,;

g;#endif

(7)

C++ Ternary Node Implementation

 // ternary-node.C

#include"ternary-node.h"

Ternary Node::Ternary Node (: operation (op), left (a), middle (b), right (c)constconstconstTree &a,Tree &b,Tree &c)const char*op, fg

voidstreamTernary Node::print (ostream &stream)constf

<<this->operation<<"("

<<this->left // recursive call

<<","<<this->middle // recursive call

<<","<<this->right // recursive call

<<")";

g

 // Modi ed classTree

classTreef// add 1 class constructor // Same as before

public:

// Same as beforeTree (constconst charTree &,*,constconstTree &);Tree &,

g;Tree::Tree (const: ptr (const charnewTree &b,Ternary Node (op, a, b, c))*op,constconstTree &c):Tree &a, fg

24

Di erences from C Implementation

 On the other hand, modifying the originalC approach requires changing:

{ The original data structures,e.g.,

structenumTree NodeNUM, UNARY, BINARY, TERNARYf f

gtag;

// same as before

union// same as before// add thisstructf Tree Node *l, *m, *r;f

gternary;

gc;

#de neternary c.ternary

g;

{ and many parts of the code,e.g.,

void// same as beforecase// same as beforeprint tree (Tree Node *root)coutprint tree (root-coutprint tree (root-coutprint tree (root-coutTERNARY: /* must be TERNARY */<<<<<<<<"(";root-root-")";break>>opop>>>[[ternary.l);ternary.m);ternary.r);01]];;; f

g

25

Summary

 OO version represents a more complete mod-eling of the problem domain { e.g., splits data structures into modules that cor-

respond to \objects" and relations in expression trees

 Use of C++ language features simplify thedesign and facilitate extensibility { e.g., the original source was hardly a ected

26

Summary (cont'd)

 Potential Problems with OO approach { Solution is very \data structure rich"

. e.g., Requires con guration management to han- dle many headers and .C les!

{ May be somewhat less ecient than original C approach

. e.g., due to virtual function overhead

{ In general, however, virtual functions may be no less inecient than large switch statements or if/elsechains:::

{ As a rule, be careful of micro vs. macro optimiza- tions

. i.e., always pro le your code!

(8)

References

Related documents

I could certainly perform hammer ons and pull offs more quickly than I could pick but I couldn't play lines of 8th or 16th notes with a solid time feel, placing accents where I

However, the predatory pricing was not fined, since the relevant measure of costs that a multi-product or multi-service postal operator benefiting from a reserved area has to

Bulk Liquid - General Tanker Terminal Code Remarks.. 1 There is safe access between the tanker

• Does your organisation handle, hold or store customers information and publicise all your services via a website?.. Provision of services

Used to each of windows forms treenode for further clarification on the control collection of the tree node represents the tree node in which the event.. Equal to the tree node that

OpenNSA/BoD GN3 &amp; NRENs User Control Inteface OpenStack NFS JunOS/HP Routing/Switching Resources Compute Resources Storage Resources Transport

However, while this survey was a tremendous success, they could only make a crude measurement of the planet mass function by fitting a power law to large bins in M sin i, they

Negative is relative high case (4.57 mm standard) and localisation of the solder paths with pins raster 1.27 mm under the case. The soldering and following solder paths with pins