roang roang - 2 months ago 22
C++ Question

Implementing polymorphism in C++

I was watching Google talk on polymorphism and clean code.

In that, the speaker was explaining how to create a clean code for an operation like 1+2*3 enter image description here

class Node{
virtual double evaluate() = 0;
};
class ValueNode :Node{
double value;
double evaluate(){
return value;
}
};
class OpNode :Node{
Node left;
Node right;
virtual double evaluate() = 0;
};
class AdditionNode : OpNode{
double evaluate(){
return left.evaluate() + right.evaluate();
}
};
class MultiplyNode : OpNode{
double evaluate(){
return left.evaluate() * right.evaluate();
}
};


I just copied the speaker's java code in c++. But in c++

Node left;
Node right;


will mean that left and right are objects of Node which is an abstract class and hence not allowed.


How do I fix this.

Answer

Polymorphism only works when you use pointers/references to objects. In Java, class objects are always allocated dynamically and referred to by pointer. So, in C++, the class declarations would need to look like this:

class Node {
public:
    virtual double evaluate() = 0;
};

class ValueNode : public Node {
public:
    double value;
    double evaluate() {
        return value;
    }
};

class OpNode : public Node {
public:
    Node *left;
    Node *right;
};

class AdditionNode : public OpNode {
public:
    double evaluate() {
        return left->evaluate() + right->evaluate();
    }
};

class MultiplyNode : public OpNode {
public:
    double evaluate() {
        return left->evaluate() * right->evaluate();
    }
};

And then you can set up the example expression 1+(2*3) like this:

ValueNode value1;
value1.value = 1;

ValueNode value2;
value2.value = 2;

ValueNode value3;
value3.value = 3;

MultiplyNode multiply;
multiply.left = &value2;
multiply.right = &value3;

AdditionNode add;
add.left = &value1;
add.right = &multiply;

double result = add.evaluate();

When add.evaluate() is called, it returns the sum of the values returned by calling left->evaluate() and right->evaluate(), where left is pointing at value1 and right is pointing at multiply.

When value1->evaluate() is called, it returns its value field, which is 1.

When multiply->evaluate() is called, it returns the product of the values returned by calling left->evaluate() and right->evaluate(), where left is pointing at value2 and right is pointing at value3.

When value2->evaluate() is called, it returns its value field, which is 2.

When value3->evaluate() is called, it returns its value field, which is 3.

Thus, add.evaluate() returns the sum of 1 plus 2*3, which is 7.