在C ++中实现多态

时间:2016-10-05 01:34:22

标签: c++ polymorphism

我在看Google talk on polymorphism and clean code

在那里,演讲者正在解释如何为1 + 2 * 3等操作创建一个干净的代码:

image

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();
    }
};

我刚刚用c ++复制了发言人的java代码。但是在c ++中

Node left;
Node right;

意味着左边和右边是Node的对象,它是一个抽象类,因此不允许。

  

我该如何解决这个问题。

编辑:我根据@Remy Lebeau提供的建议修改了代码。我预计输出为7,但我得到了687194771。

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

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

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

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

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

int _tmain(int argc, _TCHAR* argv[])
{
    ValueNode value1;
    value1.value = 1;

    ValueNode value2;
    value1.value = 2;

    ValueNode value3;
    value1.value = 3;

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

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

    int result = add.evaluate();
    cout << result;

    return 0;
}

我的错误在哪里?

4 个答案:

答案 0 :(得分:2)

多态性仅在使用指针/对象引用时才有效。在Java中,类对象总是动态分配并由指针引用。因此,在C ++中,类声明需要如下所示:

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();
    }
};

然后您可以像这样设置示例表达式1+(2*3)

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();

调用add.evaluate()时,会返回通过调用left->evaluate()right->evaluate()返回的值的总和,其中left指向value1和{ {1}}指向right

调用multiply时,会返回value1->evaluate()字段,value

调用1时,会返回通过调用multiply->evaluate()left->evaluate()返回的值的乘积,其中right->evaluate()指向left和{ {1}}指向value2

调用right时,会返回value3字段,value2->evaluate()

调用value时,会返回2字段,value3->evaluate()

因此,value会返回3add.evaluate()的总和,即1

答案 1 :(得分:0)

  

我该如何解决这个问题。

使用/etc/init.d/mysql代替Node*

Node

答案 2 :(得分:0)

您需要制作左右指针

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

    // There is no need to redeclare a pure virtual function.
    // virtual double evaluate() = 0;
};

答案 3 :(得分:0)

您不能只将Java代码复制到等效的C ++语法中,并期望它能够正常工作。

C ++对象的工作方式与Java对象完全不同。您无法将C ++对象与Java对象进行比较。它们根本不同。

与Java对象相当的C ++将是引用计数对象,如std::shared_ptr,因此等效的C ++伪代码(模仿你的风格)将是:

class OpNode :Node{
    std::shared_ptr<Node> left;
    std::shared_ptr<Node> right;
    virtual double evaluate() = 0;
};

典型的子类是:

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

我遗漏了您遗漏的相同详细信息,例如私人/公共访问课程等......