当 return 类型在编译时未知时如何避免向下转换?
How to avoid down-casting when return types are not known at compile time?
假设我有一个名为 Node
的抽象基 class。
class Node
{
public:
Node() {
leftChild = NULL;
rightChild = NULL;
};
Node * leftChild, *rightChild;
void attach(Node * LC, Node * RC) {
leftChild = LC;
rightChild = RC;
};
};
我还有多个功能(为简单起见,我将包括两个功能,但实际上这可以是任意数量)。
float add(float a, float b){return a+b;}
bool gt(float a, float b){return a>b;}
每个函数都有一个关联的 class。第一个如下
class BinaryFunction1 : public Node
{
public:
BinaryFunction1() {
};
float(*)(float, float) addition(){
return add
};
}
第二个在下面。
class BinaryFunction2 : public Node
{
public:
BinaryFunction2() {
};
bool(*)(float, float) greaterthan(){
return gt
};
}
在 main 中,我想执行类似下面的操作,作为创建链接列表的一种方式,希望构建一个抽象语法树。
BinaryFunction1 testBinaryFunction1();
BinaryFunction2 testBinaryFunction2();
testBinaryFunction1.attach(&testBinaryFunction2, &testBinaryFunction2);
dynamic_cast<BinaryFunction2 *>(testBinaryFunction1.leftChild)->greaterthan()(2.0, 4.0)
dynamic_cast
真的很丑,我看到它让我在路上绊倒了。有没有办法避免这种情况并完全摆脱它。
据我所知 Node * leftChild, * rightChild
确实是问题所在,因为我相信这是隐式向下转换发生的地方。如果我不知道它们在编译时的类型,我不确定如何声明这些指针。
我的方法看起来像这样:
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;
}
};
我不知道您想对当前尝试使用的函数指针做什么 return,但这可能与计算表达式有关。该概念可以进入 Node
接口,并且可以由每个具体类型的节点实现。不过,这需要指定 return 类型,而这在 Node
级别上是未知的。事实上,它在 compile-time 一般情况下可能是未知的 - 无效的用户输入显然不会导致 compile-time 错误,它必须导致 run-time 错误。 std::variant
在这里是一个很好的匹配(但将您限制为 compile-time 类型集,这可能就足够了)。
然后我们可以定义例如
// Function that can only add integers (throws otherwise)
BinaryFunc addI = [](TypedValue lhs, TypedValue rhs)
{
return std::get<int>(lhs) + std::get<int>(rhs);
};
像这样一起使用所有东西:
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());
}
(注意多态需要指针或引用!)
在这里试一试:https://godbolt.org/z/GNHKCy
假设我有一个名为 Node
的抽象基 class。
class Node
{
public:
Node() {
leftChild = NULL;
rightChild = NULL;
};
Node * leftChild, *rightChild;
void attach(Node * LC, Node * RC) {
leftChild = LC;
rightChild = RC;
};
};
我还有多个功能(为简单起见,我将包括两个功能,但实际上这可以是任意数量)。
float add(float a, float b){return a+b;}
bool gt(float a, float b){return a>b;}
每个函数都有一个关联的 class。第一个如下
class BinaryFunction1 : public Node
{
public:
BinaryFunction1() {
};
float(*)(float, float) addition(){
return add
};
}
第二个在下面。
class BinaryFunction2 : public Node
{
public:
BinaryFunction2() {
};
bool(*)(float, float) greaterthan(){
return gt
};
}
在 main 中,我想执行类似下面的操作,作为创建链接列表的一种方式,希望构建一个抽象语法树。
BinaryFunction1 testBinaryFunction1();
BinaryFunction2 testBinaryFunction2();
testBinaryFunction1.attach(&testBinaryFunction2, &testBinaryFunction2);
dynamic_cast<BinaryFunction2 *>(testBinaryFunction1.leftChild)->greaterthan()(2.0, 4.0)
dynamic_cast
真的很丑,我看到它让我在路上绊倒了。有没有办法避免这种情况并完全摆脱它。
据我所知 Node * leftChild, * rightChild
确实是问题所在,因为我相信这是隐式向下转换发生的地方。如果我不知道它们在编译时的类型,我不确定如何声明这些指针。
我的方法看起来像这样:
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;
}
};
我不知道您想对当前尝试使用的函数指针做什么 return,但这可能与计算表达式有关。该概念可以进入 Node
接口,并且可以由每个具体类型的节点实现。不过,这需要指定 return 类型,而这在 Node
级别上是未知的。事实上,它在 compile-time 一般情况下可能是未知的 - 无效的用户输入显然不会导致 compile-time 错误,它必须导致 run-time 错误。 std::variant
在这里是一个很好的匹配(但将您限制为 compile-time 类型集,这可能就足够了)。
然后我们可以定义例如
// Function that can only add integers (throws otherwise)
BinaryFunc addI = [](TypedValue lhs, TypedValue rhs)
{
return std::get<int>(lhs) + std::get<int>(rhs);
};
像这样一起使用所有东西:
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());
}
(注意多态需要指针或引用!)
在这里试一试:https://godbolt.org/z/GNHKCy