C++ 当涉及多态类型时,如何避免过度使用动态转换/我是否正确地将它们用于AST?
我已经编写了一个编译器,它以当前的形式工作。但是,在访问AST上的节点时,在区分节点的不同子类时,我觉得我过度使用了动态强制转换。以下是一个例子: 我有一个名为C++ 当涉及多态类型时,如何避免过度使用动态转换/我是否正确地将它们用于AST?,c++,casting,compiler-construction,polymorphism,abstract-syntax-tree,C++,Casting,Compiler Construction,Polymorphism,Abstract Syntax Tree,我已经编写了一个编译器,它以当前的形式工作。但是,在访问AST上的节点时,在区分节点的不同子类时,我觉得我过度使用了动态强制转换。以下是一个例子: 我有一个名为visit的递归方法,它为每个节点子类动态地强制转换一个节点参数。它将检查强制转换是否成功,然后采取适当的措施: VariableValue visit(Node *node) { Num* num = dynamic_cast<Num*>(node); if (num != NULL) { r
visit
的递归方法,它为每个节点子类动态地强制转换一个节点参数。它将检查强制转换是否成功,然后采取适当的措施:
VariableValue visit(Node *node) {
Num* num = dynamic_cast<Num*>(node);
if (num != NULL) {
return visit_Num(num);
}
delete num;
BinOp* binop = dynamic_cast<BinOp*>(node);
if (binop != NULL) {
return visit_BinOp(binop);
}
delete binop;
UnOp* unop = dynamic_cast<UnOp*>(node);
if (unop != NULL) {
return visit_UnaryOp(unop);
}
delete unop;
...
下面是如何在解析器中生成节点(例如,Num
node)
如果所有
节点
都包含一个标识类型的枚举
,那么为什么不将其与静态转换
而不是动态转换
一起使用呢?另外,不相关的,您应该使用nullptr
而不是NULL
“我试图通过在强制转换失败时使用delete来改进这一点。”幸运的是,这对您来说不会起任何作用,因为delete
的目标保证为空指针<代码>动态_cast不会创建新对象;它只是给你一个参考;如果您设法删除了该引用,它将影响原始对象。(顺便说一下,您的基类型似乎没有虚拟析构函数。我想这是因为您没有在摘录中包含它。)这里对“内存”没有影响。CPU,是的……另外,请查看std::variant
。它更接近您想要的功能。@LightnessRacesBY-SA3.0:可能该注释更明确:-)
class Node {
public:
virtual std::string toString() = 0;
virtual int getNodeAttribute() { return 0; }
Token token;
Node(){}
};
class BinOp : public Node{
public:
Node *left, *right;
Token op;
BinOp(Node *cleft, Token cop, Node *cright) {
left = cleft;
Node::token = cop;
op = cop;
right = cright;
}
std::string toString() {
return "BinOp Node";
}
};
class Num : public Node{
public:
TokenValue value;
Num(Token ctoken) {
Node::token = ctoken;
value = ctoken.value;
}
std::string toString() {
return "Num Node";
}
};
class UnOp : public Node {
public:
Node *expr;
UnOp(Token ctoken, Node *cexpr) {
Node::token = ctoken;
expr = cexpr;
}
std::string toString() {
return "UnOp Node";
}
};
...
Node* Parser::factor() {
...
else if (token.type == TOKENTYPE::INTEGER) {
eat(TOKENTYPE::INTEGER);
Num* numNode = new Num(token);
return numNode;
}
...