C++;如何强制转换动态派生类 我在C++编写一个翻译,作为UNI的一门课程。 基本上我用谷歌自己翻译成C++。

C++;如何强制转换动态派生类 我在C++编写一个翻译,作为UNI的一门课程。 基本上我用谷歌自己翻译成C++。,c++,casting,tree,interpreter,C++,Casting,Tree,Interpreter,使用visitor作为解释器我有两个类 BinOp : public AST Number : public AST 我的解释器类中有两个方法 class Interpreter : public NodeVisitor int visitBinOp(BinOp* node) { //example if the operation is + //return this->visit(node->left) + this->visit(node->right

使用visitor作为解释器我有两个类

BinOp : public AST

Number : public AST
我的解释器类中有两个方法

class Interpreter : public NodeVisitor

int visitBinOp(BinOp* node)
{
  //example if the operation is +
  //return this->visit(node->left) + this->visit(node->right)
}
int visitNumber(Number* node)
{
  //returns the int value that's in the node.
  //return node->value;
}
以及解释器继承的NodeVisitor中的1个方法

class NodeVisitor
int visit(AST* node)
{

  //if node is BinOp properFunction is pointer to visitBinOp

  //if node is Number properFunction is pointer tp visitNumber

  //return properFunction(node)
}
问题1:检查AST是二进制还是数字的最佳方法是什么

if(typeid(node) == typeid(BinOp*)
或 通过一些转换(当尝试动态转换时,我得到一个错误,类不是多态的)

主要问题:我需要以某种方式创建指向这些函数的指针,但不知道如何创建

编辑1 将此代码添加到NodeVisitor,但由于它包含“解释器.h” 还有翻译,包括“NodeVisitor.h”我得到

错误C2504:“NodeVisitor”:基类未定义

unsigned long int NodeVisitor::visit(AST* node)
{
  std::function<unsigned long int(Number* node)> visitNumber = std::bind(&Interpreter::VisitNumber);
  std::function<unsigned long int(BinaryOperation* node)> visitBinOp = std::bind(&Interpreter::VisitBinOp);
  if (typeid(node) == typeid(Number*))
  {
    visitNumber((Number*)node);
  }
  if (typeid(node) == typeid(BinaryOperation*))
  {
    visitBinOp((BinaryOperation*)node);
  }
}

但是我不太清楚这是怎么回事。

好的,今天早上我醒来时得到了答案。 我没有在NodeVisitor.cpp中实现visit函数(我无法访问解释器函数),而是将visit函数虚拟化并在解释器.cpp中实现

unsigned long int Interpreter::visit(AST* node)
{
  Number* number = dynamic_cast<Number*>(node);
  BinaryOperation* binOp = dynamic_cast<BinaryOperation*>(node);

  if (number)
  {
    return this->VisitNumber((Number*)node);
  }

  return this->VisitBinOp((BinaryOperation*)node);
}
无符号长整数解释器::访问(AST*节点)
{
编号*编号=动态施法(节点);
BinaryOperation*binOp=动态_转换(节点);
如果(数字)
{
返回此->访问编号((编号*)节点);
}
返回此->访问操作((二进制操作*)节点);
}

我想我的大脑需要休息一下。。。在工作中编码了8个小时,然后在家里编码了4个小时,这是连续的12个小时:D

注意:虽然有时可能需要
dynamic\u cast
,但请注意,使用它是一种“代码气味”

在面向对象编程中,通常不会要求对象输入其类型,然后根据该信息执行某些操作。你告诉对象做你需要做的事情,它会根据它是什么对象做正确的事情

那么,为什么不给
AST
一个
虚拟无符号长解释器visit(解释器*解释器)
方法,然后

unsigned long Interpreter::visit(AST *node) {
    node->InterpreterVisit(this);
}
相反?如果希望将解释器代码与AST代码分开,还可以将其实现为附件,其中AST节点拥有第二个对象,该对象实现了
explorervisit()
,然后只需要一个点来为该类型创建正确类型的附件对象(例如,使用部分模板专门化)

我对解释器的结构了解不多,无法说明它是否适用于您的设计,但我想鼓励您停下来思考是否有比
dynamic\u cast
更好的方法,只要您想使用它

有时它也可以帮助你“隐藏”施法的使用,特别是如果你发现自己经常做相同的施法。提前做一次。根据该施法将对象附加到对象上,然后调用该对象,而不是反复施法

PS:关于您的循环包含,有时您可以避免这种情况。现有几种工具:

  • 使用
    class Foo;
    (注意分号)向前声明所涉及的一个类这将告诉C++,一个类的名字不存在于整个报头中,也不在其他类的使用中。不能声明正向声明类的子类,但可以声明引用和指针。< /P>
  • 拆分标题。通常每个类都有自己的标题(
    .h
    /
    .hpp
    )和实现文件(
    .cp
    /
    .cpp
    )。这样,您可以只包含所需的类,并在其他类的标题中转发声明这些类(然后在使用这些类的实现文件中实际只包含完整的头)

  • 将你的类本身分开。例如,一个类
    MixinA
    需要包含部分类
    A
    需要包含,另一个类
    MixinB
    需要包含部分类
    B
    需要包含,然后创建
    C类:public MixinA,public MixinB…
    。这样你就有了一个同时包含两个部分的类,但又避免了循环因为只有
    C
    才能看到整个画面


  • 如果您使用智能指针,您可以使用
    std::dynamic\u pointer\u cast
    如果您发现类不是多态的错误,您可能需要添加一个虚拟函数(例如至少是析构函数)。但您可能走错了方向。您应该有一个虚拟函数,可以调用每个派生类实现。应该没有理由知道节点的类型。我需要以某种方式创建指向这些函数的指针,但不知道如何查找ye
    std::function
    以及lambda表达式。对于在那里,我把开始读写C++解释的错误读出来,这是一个重大的挑战。我曾经用C++的小样本解释器编写了答案。也许,这可以提供一些额外的启发。每个派生的
    AST::Expr
    提供的方法。可能是,这是您正在寻找的缺失部分。是我的代码。解释器从解析器获取一个AST(抽象语法树),并根据类型调用相应的函数。我有7个AST,无法进行7个不同的解析()解析器返回给解释器的函数。
    unsigned long Interpreter::visit(AST *node) {
        node->InterpreterVisit(this);
    }