C++ Example
// OOP = ADT + inheritence + dynamic typing
// See also Andrew Koenig JOOP August 1988
#include
int valtab[127] ; //used for integer values of variables
class Node {
protected:
Node(){ use = 1; }
virtual void print(ostream&) = 0;
virtual ~Node() {} //note virtual destructor
virtual int eval() = 0;
private:
friend class Tree;
friend ostream& operator<<(ostream&, const Tree&);
int use; //reference count
};
class Tree {
public:
Tree(int); //constant
Tree(char); //variable
Tree(char*, Tree); //unary operator
Tree(char*, Tree, Tree); //binary operator
Tree(const Tree& t) { p = t.p; ++p -> use;}
~Tree() {if (--p ->use == 0) delete p; }
void operator=(const Tree& t);
int eval() {return p->eval();}
private:
friend class Node;
friend ostream& operator<<(ostream&, const Tree&);
Node* p; //polymorphic hierarchy
};
void Tree:: operator=(const Tree& t)
{
++t.p -> use;
if ( --p -> use == 0)
delete p;
p = t.p;
}
ostream& operator<<(ostream& o, const Tree& t)
{
t.p -> print(o);
return (o);
}
class LeafNode: public Node {
private:
friend class Tree;
void print(ostream& o) = 0;
virtual int eval() = 0;
};
class IntNode: public LeafNode {
public:
int eval(){ return n;}
private:
friend class Tree;
int n;
void print(ostream& o) { o << n ;}
IntNode(int k): n (k) {}
};
class IdNode: public LeafNode {
public:
int eval(){ return valtab[name];}
private:
friend class Tree;
char name;
void print(ostream& o) { o << name ;}
IdNode(char id): name (id) {}
};
class UnaryNode: public Node {
public:
int eval();
private:
friend class Tree;
char* op;
Tree opnd;
UnaryNode(char* a, Tree b): op(a), opnd(b) {}
void print (ostream& o) {o << "(" << op << opnd << ")";}
};
int UnaryNode::eval()
{
switch (op[0]){
case '-': return (-opnd.eval());
case '+': return (+opnd.eval());
default: cerr << "no operand\n" << endl;
return 0;
}
}
class BinaryNode: public Node {
public:
int eval();
private:
friend class Tree;
char* op;
Tree left;
Tree right;
BinaryNode(char* a, Tree b, Tree c): op(a), left(b), right(c){}
void print (ostream& o) {o << "(" << left << op << right << ")";}
};
int BinaryNode::eval()
{
switch (op[0]){
case '-': return (left.eval() - right.eval());
case '+': return (left.eval() + right.eval());
case '*': return (left.eval() * right.eval());
default: cerr << "no operand\n" << endl;
return 0;
}
}
Tree::Tree(int n)
{
p = new IntNode(n);
}
Tree::Tree(char id)
{
p = new IdNode(id);
}
Tree::Tree(char* op, Tree t)
{
p = new UnaryNode(op, t);
}
Tree::Tree(char* op, Tree left, Tree right)
{
p = new BinaryNode(op, left, right);
}
int main()
{
valtab['A'] = 3; valtab['B'] = 4;
cout << "A = 3, B = 4" << endl;
Tree t1 = Tree("*", Tree("-", 5), Tree("+", 'A', 4));
Tree t2 = Tree("+", Tree("-", 'A', 1), Tree("+", t1, 'B'));
cout << "t1 = " << t1 << " ; t2 = " << t2 << endl;
cout << "t1:" << t1.eval() << " t2:" << t2.eval() << endl;
}