C ++ meditation notes - Chapter VIII: An instance of object-oriented programming

Object-oriented programming has three elements: data abstraction, inheritance, and dynamic binding.

 

Compile Precautions:

Function ostream & operator << (ostream &, const Expr &) To access the class Expr_node of print, but the print is protected.

So should function ostream & operator << (ostream &, const Expr &) declared as a friend class Expr_node function.

 

Friend Function class Expr_node Expr class parameter are in, but this time has not yet declared class Expr. So to add a class Expr before class Expr_node;

The following three Expr class member functions, because you want to create a class Int_node, class Unary_node, class Unary_node three classes of objects, but this time three classes have not yet declared.

So this three-defined function to be placed after class Int_node, class Unary_node, class Unary_node three class declaration.

Expr(int);

Expr(const string&, Expr);

Expr(const string&, Expr, Expr);

 

#include <iostream>

#include <string>

using namespace std;

class Expr;

class Expr_node{

    friend class Expr;

    friend ostream& operator<<(ostream&,const Expr&);

    int use;

protected:

    Expr_node(): use(1) {}

    virtual void print(ostream&) const = 0;

    virtual ~Expr_node() {}

    virtual int eval() const = 0;

};

class Expr{

    friend class Expr_node;

    friend ostream& operator<<(ostream&, const Expr&);

    Expr_node* p;

public:

    Expr(int);

    Expr(const string&, Expr);

    Expr(const string&, Expr, Expr);

    Expr(const string&, Expr, Expr, Expr);

    Expr(const Expr& t) { p = t.p; ++p->use; }

    Expr& operator=(const Expr& rhs){

        rhs.p->use++;

        if(--p->use == 0)

            delete p;

        p = rhs.p;

        return *this;

    }

    ~Expr() { if(--p->use == 0) delete p; }

    int eval() const { return p->eval(); }

};

class Int_node: public Expr_node{

    friend class Expr;

    int n;

    Int_node(int k): n(k) {}

    void print(ostream& o) const { o << n;}

    int eval() const { return n; }

};

class Unary_node: public Expr_node{

    friend class Expr;

    string op;

    Expr opnd;

    Unary_node(const string& a, Expr b): op(a), opnd(b) {}

    void print(ostream& o) const { o << "(" << op << opnd << ")"; }

    int eval() const {

        if(op == "-")

            return -opnd.eval();

        throw "error, bad op" + op + "int UnaryNode";

    }

};

class Binary_node: public Expr_node{

    friend class Expr;

    string op;

    Expr left;

    Expr right;

    Binary_node(const string& a, Expr b, Expr c): op(a), left(b), right(c) {}

    void print(ostream& o) const { o << "(" << left << op << right << ")"; }

    int eval() const{

        int op1 = left.eval();

        int op2 = right.eval();

 

        if(op == "-") return op1 - op2;

        if(op == "+") return op1 + op2;

        if(op == "*") return op1 * op2;

        if(op == "/" && op2 != 0) return op1 / op2;

        throw "error, bad op" + op + "int BinaryNode";

    }  

};

class Ternary_node: public Expr_node{

    friend class Expr;

    string op;

    Expr left;

    Expr middle;

    Expr right;

    Ternary_node(const string& a, Expr b, Expr c, Expr d): op(a), left(b), middle(c), right(d) {}

    void print(ostream& o) const{

        o << "(" << left << "?" << middle << ":" << right << ")";

    }

    int eval() const{

        if(left.eval())

            return middle.eval();

        else

            return right.eval();

    }

};

Expr::Expr(int n) { p = new Int_node(n); }

Expr::Expr(const string& op, Expr t) { p = new Unary_node(op, t); }

Expr::Expr(const string &op, Expr left, Expr right) { p = new Binary_node(op, left, right); }

Expr::Expr(const string &op, Expr left, Expr middle, Expr right) { p = new Ternary_node(op, left, middle, right); }

ostream& operator<<(ostream& o, const Expr& t)

{

    t.p->print(o);

    return o;

}

int main(int argc, char const *argv[])

{

    Expr t = Expr("*", Expr("-", 5), Expr("+", 3, 4));

    cout << t << "=" << t.eval() << endl;

    t = Expr("*", t, t);

    cout << t << "=" << t.eval() << endl;

    //Expr k = Expr("?", t, Expr("-", 5), Expr("+", 3, 4));

    //cout << k << endl;

    return 0;

}

 

Guess you like

Origin www.cnblogs.com/vonyoven/p/11778297.html