Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当编译时返回类型未知时,如何避免向下转换?_C++_Linked List_Abstract Syntax Tree_Downcast - Fatal编程技术网

C++ 当编译时返回类型未知时,如何避免向下转换?

C++ 当编译时返回类型未知时,如何避免向下转换?,c++,linked-list,abstract-syntax-tree,downcast,C++,Linked List,Abstract Syntax Tree,Downcast,假设我有一个名为Node的抽象基类 class Node { public: Node() { leftChild = NULL; rightChild = NULL; }; Node * leftChild, *rightChild; void attach(Node * LC, Node * RC) { leftChild = LC; rightChild = RC; }; }; 我

假设我有一个名为
Node
的抽象基类

class Node
{
public:
    Node() {
        leftChild = NULL;
        rightChild = NULL;
    };

    Node * leftChild, *rightChild;

    void attach(Node * LC, Node * RC) {
        leftChild = LC;
        rightChild = RC;
    };
};
我也有多个函数(为了简单起见,我将包括两个函数,但实际上这可以是任意数量)

每个函数都有一个关联的类。第一点如下

class BinaryFunction1 : public Node
{
public:
    BinaryFunction1() {
    };

    float(*)(float, float) addition(){
        return add
    };
}
第二个在下面

class BinaryFunction2 : public Node
{
public:
    BinaryFunction2() {
    };

    bool(*)(float, float) greaterthan(){
        return gt
    };
}
主要来说,我想执行下面这样的操作,作为创建链表的一种方式,希望构建一个抽象语法树

BinaryFunction1 testBinaryFunction1();
BinaryFunction2 testBinaryFunction2();

testBinaryFunction1.attach(&testBinaryFunction2, &testBinaryFunction2);

dynamic_cast<BinaryFunction2 *>(testBinaryFunction1.leftChild)->greaterthan()(2.0, 4.0)
BinaryFunction1 testBinaryFunction1();
BinaryFunction2 testBinaryFunction2();
testBinaryFunction1.attach(&testBinaryFunction2,&testBinaryFunction2);
dynamic_cast(testBinaryFunction1.leftChild)->greaterthan()(2.0,4.0)
dynamic_cast
真的很难看,我看到它把我绊倒在路上。有没有一种方法可以避免这种情况,并彻底摆脱它


就我所见,
Node*leftChild、*righchild
确实是个问题,因为我相信这就是隐式向下转换发生的地方。如果我不知道编译时指针的类型,我不确定如何声明这些指针。

我的方法如下:

using TypedValue = std::variant<int, float, bool>;

using BinaryFunc = std::function<TypedValue(TypedValue, TypedValue)>;

struct Node
{
public:
    Node() {
        leftChild = nullptr;
        rightChild = nullptr;
    };

    virtual ~Node() = default;

    Node * leftChild, *rightChild;

    void attach(Node * LC, Node * RC) {
        leftChild = LC;
        rightChild = RC;
    };

    virtual TypedValue evaluate() = 0;
};


struct BinaryFuncNode : public Node
{
    BinaryFuncNode(BinaryFunc func) : Node(), binaryFunc(func) {}

    BinaryFunc binaryFunc;

    TypedValue evaluate() override
    {
        return binaryFunc(leftChild->evaluate(), rightChild->evaluate());
    }
};

struct ConstantNode : public Node
{
    ConstantNode(TypedValue val) : Node(), value(val) {}

    TypedValue value;

    TypedValue evaluate() override
    {
        return value;
    }
};
int main()
{
    auto cnode = std::make_unique<ConstantNode>(10);
    auto bfnode = std::make_unique<BinaryFuncNode>(addI);
    bfnode->attach(cnode.get(), cnode.get());
    return std::get<int>(bfnode->evaluate());
}
把所有东西都用在一起,就像这样:

using TypedValue = std::variant<int, float, bool>;

using BinaryFunc = std::function<TypedValue(TypedValue, TypedValue)>;

struct Node
{
public:
    Node() {
        leftChild = nullptr;
        rightChild = nullptr;
    };

    virtual ~Node() = default;

    Node * leftChild, *rightChild;

    void attach(Node * LC, Node * RC) {
        leftChild = LC;
        rightChild = RC;
    };

    virtual TypedValue evaluate() = 0;
};


struct BinaryFuncNode : public Node
{
    BinaryFuncNode(BinaryFunc func) : Node(), binaryFunc(func) {}

    BinaryFunc binaryFunc;

    TypedValue evaluate() override
    {
        return binaryFunc(leftChild->evaluate(), rightChild->evaluate());
    }
};

struct ConstantNode : public Node
{
    ConstantNode(TypedValue val) : Node(), value(val) {}

    TypedValue value;

    TypedValue evaluate() override
    {
        return value;
    }
};
int main()
{
    auto cnode = std::make_unique<ConstantNode>(10);
    auto bfnode = std::make_unique<BinaryFuncNode>(addI);
    bfnode->attach(cnode.get(), cnode.get());
    return std::get<int>(bfnode->evaluate());
}
intmain()
{
自动cnode=std::使_唯一(10);
自动bfnode=std::使_唯一(addI);
bfnode->attach(cnode.get(),cnode.get());
返回std::get(bfnode->evaluate());
}
(请注意,变形需要指针或引用!)


在这里使用它:

Have
Node
使用
virtualbool(*)(float,float)greaterthan()=0指定接口。或例如
virtualbool(*)(float,float)greaterthan(){return nullptr;}
virtualbool(*)(float,float)greaterthan(){throw Node::exception_greather_then_not_found();}
@KamilCuk,但它不可扩展。您必须为每个新操作更改基类。一个不可扩展的多态性解决方案马上就被怀疑了。我想知道是否能帮上忙。基类中可以有一个
get
函数,它是一个模板,并从派生类型返回函数指针。这使您可以在编译时设置关系,这样就不必强制转换。访客模式经常会纠正AST问题。你看了
std::variant
/
std::visit
了吗?我看了,我也考虑了访问者模式,尽管我不知道如何在这里实现它。关于这方面的一些指导将非常有用。我也看过STD::变种,但我有点认为作弊…也许我不应该@麦克斯兰霍夫:谢谢,这真是太棒了!