重写方法调用中的C++奇数异常

重写方法调用中的C++奇数异常,c++,function,methods,C++,Function,Methods,我有一个基类a,它永远不会被实例化: class A { public: virtual void visit(Visitor * v) { } }; class Visitor { public: virtual void visit(A * a) { } virtual void visit(B * b) { } virtual void visit(C * c) { } virtual void visit(D * d) { } }; Visi

我有一个基类a,它永远不会被实例化:

class A {
public:
    virtual void visit(Visitor * v) { }
};
class Visitor {
public:
    virtual void visit(A * a) { }

    virtual void visit(B * b) { }
    virtual void visit(C * c) { }
    virtual void visit(D * d) { }
};
Visitor也只是一个基类,它也永远不会被实例化:

class A {
public:
    virtual void visit(Visitor * v) { }
};
class Visitor {
public:
    virtual void visit(A * a) { }

    virtual void visit(B * b) { }
    virtual void visit(C * c) { }
    virtual void visit(D * d) { }
};
以下是B、C和D类:

class B : public A {
public:
    virtual void visit(Visitor * v) { v->visit(this); }
};

class C : public A {
public:
    virtual void visit(Visitor * v) { v->visit(this); }
};

class D : public A {
public:
    virtual void visit(Visitor * v) { v->visit(this); }
};
现在我继承访客:

class FooVisitor : public Visitor {
public:
    virtual void visit(A * a) { a->visit(this); }

    virtual void visit(B * b) { /*do something*/ }
    virtual void visit(C * c) { /*do something*/ }
    virtual void visit(D * d) { /*do something*/ }
};
最后,我提出主要问题:

int main() {
    A * something = getSomethingLikeA(); // Returns a pointer to a B, C or D instance
    FooVisitor * v = new FooVisitor();
    v->visit(something);
    return 0;
}
我在visit方法调用中得到一个未处理的异常。更具体地说,以下是我的情况视频:

我不知道是什么原因,调试器并没有真正帮助我

编辑:
下面是实际程序的源代码:8.31 KiB

在大多数情况下,您创建和设计的层次结构将导致无限递归调用。我相信这就是例外的原因

    A * something = getSomethingLikeA();   
//Let's say you get object of type B.

    v->visit(something);
///would call FooVisitor's
    virtual void visit(A * a) { a->visit(this); }
//then class B's
    virtual void visit(Visitor * v) { v->visit(this); }
//and then again Foovisitor's
    virtual void visit(A * a) { a->visit(this); }  ////huh? I just called it back 
                                                   ////few stack frames.

在精疲力竭之后,它找到的唯一方法就是直接抛出异常来消除这些特性…

通过查看您的代码,您可以看到Parser类的一些parseXYZ成员函数在所有代码路径中都缺少一条return语句,这是你正在经历的未定义行为的途径:

Exp * parseRelExp() {
    Exp * left = parseBinaryExp();
    if (lookahead->type == EQUALS || lookahead->type == NOT_EQUALS || lookahead->type == GREATER_THAN || lookahead->type == LESS_THAN || lookahead->type == GOE_THAN || lookahead->type == LOE_THAN) {
        TokenType op = lookahead->type;
        next();
        Exp * right = parseExp();
        if (right != nullptr) {
            return new RelExp(left, op, right);
        }
        else expect("Expression");
    }
    // what if we get here??
}

在大多数情况下,尽管返回值尚未定义,但它是堆栈中的任意垃圾,如果将其解释为指针,则在取消引用时可能会导致应用程序崩溃。

Pro提示:使用struct提问,并节省大量的公共噪音。这集中了问题的焦点,缩短了文章的篇幅。你可能想了解你从未实例化过的基函数的纯虚拟成员函数。这绝对是第一次有人创建了一个关于编码问题的视频。这比截图快了一倍。我真的不知道是什么原因造成的!是的,我知道我应该使用纯虚拟函数…请提供我可以编译和运行的源代码来重现错误。您的代码会产生大量编译错误。在修复这些异常之后,我不会得到任何未处理的异常